1*758e9fbaSOystein Eftevaag#!/usr/bin/env python3 2*758e9fbaSOystein Eftevaag# SPDX-License-Identifier: BSD-2-Clause 3*758e9fbaSOystein Eftevaagimport os 4*758e9fbaSOystein Eftevaagimport argparse 5*758e9fbaSOystein Eftevaagimport itertools 6*758e9fbaSOystein Eftevaag 7*758e9fbaSOystein Eftevaag# Makefile-fuzz-generated.am is created from this template. 8*758e9fbaSOystein EftevaagMAKEFILE_FUZZ = '''# SPDX-License-Identifier: BSD-2-Clause 9*758e9fbaSOystein Eftevaag# Copyright (c) 2018 Intel Corporation 10*758e9fbaSOystein Eftevaag# All rights reserved. 11*758e9fbaSOystein Eftevaag 12*758e9fbaSOystein Eftevaagif ENABLE_TCTI_FUZZING 13*758e9fbaSOystein EftevaagTESTS_FUZZ = %s 14*758e9fbaSOystein Eftevaag%s 15*758e9fbaSOystein Eftevaagendif # ENABLE_TCTI_FUZZING 16*758e9fbaSOystein Eftevaag''' 17*758e9fbaSOystein Eftevaag# Each fuzz target in Makefile-fuzz-generated.am is created from this template. 18*758e9fbaSOystein EftevaagMAKEFILE_FUZZ_TARGET = ''' 19*758e9fbaSOystein Eftevaagnoinst_PROGRAMS += test/fuzz/%s.fuzz 20*758e9fbaSOystein Eftevaagtest_fuzz_%s_fuzz_CPPFLAGS = $(FUZZ_CPPFLAGS) 21*758e9fbaSOystein Eftevaagtest_fuzz_%s_fuzz_LDADD = $(FUZZLDADD) 22*758e9fbaSOystein Eftevaagnodist_test_fuzz_%s_fuzz_SOURCES = test/fuzz/main-sapi.cpp \\ 23*758e9fbaSOystein Eftevaag test/fuzz/%s.fuzz.cpp 24*758e9fbaSOystein Eftevaag 25*758e9fbaSOystein EftevaagDISTCLEANFILES += test/fuzz/%s.fuzz.cpp''' 26*758e9fbaSOystein Eftevaag# Common include definitions needed for fuzzing an SAPI call 27*758e9fbaSOystein EftevaagSAPI_TEMPLATE_HEADER = '''/* SPDX-License-Identifier: BSD-2-Clause */ 28*758e9fbaSOystein Eftevaag/*********************************************************************** 29*758e9fbaSOystein Eftevaag * Copyright (c) 2018, Intel Corporation 30*758e9fbaSOystein Eftevaag * 31*758e9fbaSOystein Eftevaag * All rights reserved. 32*758e9fbaSOystein Eftevaag ***********************************************************************/ 33*758e9fbaSOystein Eftevaag#ifdef HAVE_CONFIG_H 34*758e9fbaSOystein Eftevaag#include <config.h> 35*758e9fbaSOystein Eftevaag#endif 36*758e9fbaSOystein Eftevaag 37*758e9fbaSOystein Eftevaag#include <inttypes.h> 38*758e9fbaSOystein Eftevaag#include <stdbool.h> 39*758e9fbaSOystein Eftevaag#include <stdio.h> 40*758e9fbaSOystein Eftevaag#include <string.h> 41*758e9fbaSOystein Eftevaag#include <poll.h> 42*758e9fbaSOystein Eftevaag#include <stdarg.h> 43*758e9fbaSOystein Eftevaag 44*758e9fbaSOystein Eftevaag#include <setjmp.h> 45*758e9fbaSOystein Eftevaag 46*758e9fbaSOystein Eftevaagextern "C" { 47*758e9fbaSOystein Eftevaag#include "tss2_mu.h" 48*758e9fbaSOystein Eftevaag#include "tss2_sys.h" 49*758e9fbaSOystein Eftevaag#include "tss2_tcti_device.h" 50*758e9fbaSOystein Eftevaag 51*758e9fbaSOystein Eftevaag#include "tss2-tcti/tcti-common.h" 52*758e9fbaSOystein Eftevaag#include "tss2-tcti/tcti-device.h" 53*758e9fbaSOystein Eftevaag 54*758e9fbaSOystein Eftevaag#define LOGMODULE fuzz 55*758e9fbaSOystein Eftevaag#include "tss2_tcti.h" 56*758e9fbaSOystein Eftevaag#include "util/log.h" 57*758e9fbaSOystein Eftevaag#include "test.h" 58*758e9fbaSOystein Eftevaag#include "test-options.h" 59*758e9fbaSOystein Eftevaag#include "context-util.h" 60*758e9fbaSOystein Eftevaag#include "tss2-sys/sysapi_util.h" 61*758e9fbaSOystein Eftevaag#include "tcti/tcti-fuzzing.h" 62*758e9fbaSOystein Eftevaag} 63*758e9fbaSOystein Eftevaag 64*758e9fbaSOystein Eftevaagextern "C" 65*758e9fbaSOystein Eftevaagint 66*758e9fbaSOystein Eftevaagtest_invoke ( 67*758e9fbaSOystein Eftevaag TSS2_SYS_CONTEXT *sysContext)''' 68*758e9fbaSOystein Eftevaag# Template to call a SAPI _Complete function which takes no arguments 69*758e9fbaSOystein EftevaagSAPI_COMPLETE_TEMPLATE_NO_ARGS = SAPI_TEMPLATE_HEADER + ''' 70*758e9fbaSOystein Eftevaag{ 71*758e9fbaSOystein Eftevaag %s (sysContext); 72*758e9fbaSOystein Eftevaag 73*758e9fbaSOystein Eftevaag return EXIT_SUCCESS; 74*758e9fbaSOystein Eftevaag} 75*758e9fbaSOystein Eftevaag''' 76*758e9fbaSOystein Eftevaag# Template to call a SAPI _Complete function which takes arguments 77*758e9fbaSOystein EftevaagSAPI_COMPLETE_TEMPLATE_HAS_ARGS = SAPI_TEMPLATE_HEADER + ''' 78*758e9fbaSOystein Eftevaag{ 79*758e9fbaSOystein Eftevaag %s 80*758e9fbaSOystein Eftevaag 81*758e9fbaSOystein Eftevaag %s ( 82*758e9fbaSOystein Eftevaag sysContext, 83*758e9fbaSOystein Eftevaag %s 84*758e9fbaSOystein Eftevaag ); 85*758e9fbaSOystein Eftevaag 86*758e9fbaSOystein Eftevaag return EXIT_SUCCESS; 87*758e9fbaSOystein Eftevaag} 88*758e9fbaSOystein Eftevaag''' 89*758e9fbaSOystein Eftevaag# Template to call a SAPI _Prepare function 90*758e9fbaSOystein EftevaagSAPI_PREPARE_TEMPLATE_HAS_ARGS = SAPI_TEMPLATE_HEADER + ''' 91*758e9fbaSOystein Eftevaag{ 92*758e9fbaSOystein Eftevaag int ret; 93*758e9fbaSOystein Eftevaag %s 94*758e9fbaSOystein Eftevaag 95*758e9fbaSOystein Eftevaag ret = fuzz_fill ( 96*758e9fbaSOystein Eftevaag sysContext, 97*758e9fbaSOystein Eftevaag %d, 98*758e9fbaSOystein Eftevaag %s 99*758e9fbaSOystein Eftevaag ); 100*758e9fbaSOystein Eftevaag if (ret) { 101*758e9fbaSOystein Eftevaag return ret; 102*758e9fbaSOystein Eftevaag } 103*758e9fbaSOystein Eftevaag 104*758e9fbaSOystein Eftevaag %s ( 105*758e9fbaSOystein Eftevaag sysContext, 106*758e9fbaSOystein Eftevaag %s 107*758e9fbaSOystein Eftevaag ); 108*758e9fbaSOystein Eftevaag 109*758e9fbaSOystein Eftevaag return EXIT_SUCCESS; 110*758e9fbaSOystein Eftevaag} 111*758e9fbaSOystein Eftevaag''' 112*758e9fbaSOystein Eftevaag 113*758e9fbaSOystein Eftevaagdef gen_file(function): 114*758e9fbaSOystein Eftevaag ''' 115*758e9fbaSOystein Eftevaag Generate a cpp file used as the fuzz target given the function definition 116*758e9fbaSOystein Eftevaag from a header file. 117*758e9fbaSOystein Eftevaag ''' 118*758e9fbaSOystein Eftevaag # Parse the function name from the function definition 119*758e9fbaSOystein Eftevaag function_name = function.split('\n')[0]\ 120*758e9fbaSOystein Eftevaag .replace('TSS2_RC', '')\ 121*758e9fbaSOystein Eftevaag .replace('(', '')\ 122*758e9fbaSOystein Eftevaag .strip() 123*758e9fbaSOystein Eftevaag # Parse the function arguments into an array. Do not include sysContext. 124*758e9fbaSOystein Eftevaag args = [arg.strip() \ 125*758e9fbaSOystein Eftevaag for arg in function[function.index('(') + 1:function.index(');')]\ 126*758e9fbaSOystein Eftevaag .split(',') \ 127*758e9fbaSOystein Eftevaag if not 'TSS2_SYS_CONTEXT' in arg] 128*758e9fbaSOystein Eftevaag # Prepare and Complete functions require different methods of generation. 129*758e9fbaSOystein Eftevaag # Call the appropriate function to generate a cpp target specific to that 130*758e9fbaSOystein Eftevaag # type of function. 131*758e9fbaSOystein Eftevaag if '_Complete' in function_name: 132*758e9fbaSOystein Eftevaag return gen_complete(function, function_name, args) 133*758e9fbaSOystein Eftevaag if '_Prepare' in function_name: 134*758e9fbaSOystein Eftevaag return gen_prepare(function, function_name, args) 135*758e9fbaSOystein Eftevaag raise NotImplementedError('Unknown function type %r' % (function_name,)) 136*758e9fbaSOystein Eftevaag 137*758e9fbaSOystein Eftevaagdef gen_complete(function, function_name, args): 138*758e9fbaSOystein Eftevaag ''' 139*758e9fbaSOystein Eftevaag Generate the cpp fuzz target for a SAPI _Complete call 140*758e9fbaSOystein Eftevaag ''' 141*758e9fbaSOystein Eftevaag if not args: 142*758e9fbaSOystein Eftevaag # Fill in the no args template. Simple case. 143*758e9fbaSOystein Eftevaag return function_name, SAPI_COMPLETE_TEMPLATE_NO_ARGS % (function_name) 144*758e9fbaSOystein Eftevaag # Generate the cpp variable definitions. 145*758e9fbaSOystein Eftevaag arg_definitions = (';\n' + ' ' * 4).join([ 146*758e9fbaSOystein Eftevaag arg.replace('*', '') for arg in args]) + ';' 147*758e9fbaSOystein Eftevaag # Generate the cpp arguments. For arguments that are pointers find replace * 148*758e9fbaSOystein Eftevaag # with & so that we pass a pointer to the definition which has been 149*758e9fbaSOystein Eftevaag # allocated on the stack. 150*758e9fbaSOystein Eftevaag arg_call = (',\n' + ' ' * 8).join([ 151*758e9fbaSOystein Eftevaag arg.replace('*', '&').split()[-1] for arg in args]) 152*758e9fbaSOystein Eftevaag # Fill in the template 153*758e9fbaSOystein Eftevaag return function_name, SAPI_COMPLETE_TEMPLATE_HAS_ARGS % (arg_definitions, 154*758e9fbaSOystein Eftevaag function_name, 155*758e9fbaSOystein Eftevaag arg_call) 156*758e9fbaSOystein Eftevaag 157*758e9fbaSOystein Eftevaagdef gen_prepare(function, function_name, args): 158*758e9fbaSOystein Eftevaag ''' 159*758e9fbaSOystein Eftevaag Generate the cpp fuzz target for a SAPI _Prepare call 160*758e9fbaSOystein Eftevaag ''' 161*758e9fbaSOystein Eftevaag if not args: 162*758e9fbaSOystein Eftevaag return function_name, None 163*758e9fbaSOystein Eftevaag # Generate the cpp variable definitions. Make sure to initialize to empty 164*758e9fbaSOystein Eftevaag # structs (works for initializing anything) or cpp compiler will complain. 165*758e9fbaSOystein Eftevaag arg_definitions = (' = {0};\n' + ' ' * 4).join([ 166*758e9fbaSOystein Eftevaag arg.replace('*', '').replace('const', '') for arg in args]) + ' = {0};' 167*758e9fbaSOystein Eftevaag # Generate the cpp arguments. For arguments that are pointers find replace * 168*758e9fbaSOystein Eftevaag # with & so that we pass a pointer to the definition which has been 169*758e9fbaSOystein Eftevaag # allocated on the stack. 170*758e9fbaSOystein Eftevaag arg_call = (',\n' + ' ' * 8).join([ 171*758e9fbaSOystein Eftevaag arg.replace('*', '&').split()[-1] for arg in args]) 172*758e9fbaSOystein Eftevaag # Generate the call to fuzz_fill. The call should be the sysContext, double 173*758e9fbaSOystein Eftevaag # the number of arguments for the _Prepare call, and then for each _Prepare 174*758e9fbaSOystein Eftevaag # argument pass two to fuzz_fill, the sizeof the _Prepare argument, and a 175*758e9fbaSOystein Eftevaag # pointer to it. 176*758e9fbaSOystein Eftevaag fill_fuzz_args = (',\n' + ' ' * 8).join([ 177*758e9fbaSOystein Eftevaag ('sizeof (%s), &%s' % \ 178*758e9fbaSOystein Eftevaag tuple([arg.replace('*', '').split()[-1]] * 2)) \ 179*758e9fbaSOystein Eftevaag for arg in args]) 180*758e9fbaSOystein Eftevaag # Fill in the template 181*758e9fbaSOystein Eftevaag return function_name, SAPI_PREPARE_TEMPLATE_HAS_ARGS % (arg_definitions, 182*758e9fbaSOystein Eftevaag len(args) * 2, 183*758e9fbaSOystein Eftevaag fill_fuzz_args, 184*758e9fbaSOystein Eftevaag function_name, 185*758e9fbaSOystein Eftevaag arg_call) 186*758e9fbaSOystein Eftevaag 187*758e9fbaSOystein Eftevaagdef functions_from_include(header): 188*758e9fbaSOystein Eftevaag ''' 189*758e9fbaSOystein Eftevaag Parse out and yield each function definition from a header file. 190*758e9fbaSOystein Eftevaag ''' 191*758e9fbaSOystein Eftevaag with open(header, 'r') as header_fd: 192*758e9fbaSOystein Eftevaag current_function = '' 193*758e9fbaSOystein Eftevaag for line in header_fd: 194*758e9fbaSOystein Eftevaag # Functions we are interested in start with _Complete or _Prepare 195*758e9fbaSOystein Eftevaag if '_Complete' in line or '_Prepare' in line: 196*758e9fbaSOystein Eftevaag # Set the current_function to this line 197*758e9fbaSOystein Eftevaag current_function = line 198*758e9fbaSOystein Eftevaag elif current_function and ');' in line: 199*758e9fbaSOystein Eftevaag # When we reach the closing parenthesis yield the function 200*758e9fbaSOystein Eftevaag yield current_function + line.rstrip() 201*758e9fbaSOystein Eftevaag current_function = '' 202*758e9fbaSOystein Eftevaag elif current_function: 203*758e9fbaSOystein Eftevaag # Add all the arguments to the function 204*758e9fbaSOystein Eftevaag current_function += line 205*758e9fbaSOystein Eftevaag 206*758e9fbaSOystein Eftevaagdef gen_files(header): 207*758e9fbaSOystein Eftevaag # Generate a fuzz target cpp file from each function in the header file 208*758e9fbaSOystein Eftevaag for current_function in functions_from_include(header): 209*758e9fbaSOystein Eftevaag function_name, contents = gen_file(current_function) 210*758e9fbaSOystein Eftevaag # Skip the yield if there is no fuzz target that can be generated 211*758e9fbaSOystein Eftevaag if contents is None: 212*758e9fbaSOystein Eftevaag continue 213*758e9fbaSOystein Eftevaag # Yield the function name and the contents of its generated file 214*758e9fbaSOystein Eftevaag yield function_name, contents 215*758e9fbaSOystein Eftevaag 216*758e9fbaSOystein Eftevaagdef main(): 217*758e9fbaSOystein Eftevaag parser = argparse.ArgumentParser(description='Generate libfuzzer for sapi') 218*758e9fbaSOystein Eftevaag parser.add_argument('--header', default='include/tss2/tss2_sys.h', 219*758e9fbaSOystein Eftevaag help='Header file to look in (default include/tss2/tss2_sys.h)') 220*758e9fbaSOystein Eftevaag args = parser.parse_args() 221*758e9fbaSOystein Eftevaag 222*758e9fbaSOystein Eftevaag functions = dict(gen_files(args.header)) 223*758e9fbaSOystein Eftevaag # Write the generated target to the file for its function name 224*758e9fbaSOystein Eftevaag for function_name, contents in functions.items(): 225*758e9fbaSOystein Eftevaag filepath = os.path.join('test', 'fuzz', function_name + '.fuzz.cpp') 226*758e9fbaSOystein Eftevaag with open(filepath, 'w') as fuzzer_fd: 227*758e9fbaSOystein Eftevaag fuzzer_fd.write(contents) 228*758e9fbaSOystein Eftevaag # Fill in the Makefile-fuzz-generated.am template using the function names. 229*758e9fbaSOystein Eftevaag # Create a list of the compiled fuzz targets 230*758e9fbaSOystein Eftevaag files = ' \\\n '.join(['test/fuzz/%s.fuzz' % (function) \ 231*758e9fbaSOystein Eftevaag for function in functions]) 232*758e9fbaSOystein Eftevaag # Create the Makefile targets for each generated file 233*758e9fbaSOystein Eftevaag targets = '\n'.join([MAKEFILE_FUZZ_TARGET % tuple(list(itertools.chain(\ 234*758e9fbaSOystein Eftevaag ([function] * 6)))) for function in functions]) 235*758e9fbaSOystein Eftevaag # Write out the Makefile-fuzz-generated.am file 236*758e9fbaSOystein Eftevaag with open('Makefile-fuzz-generated.am', 'w') as makefile_fd: 237*758e9fbaSOystein Eftevaag makefile_fd.write(MAKEFILE_FUZZ % (files, targets)) 238*758e9fbaSOystein Eftevaag 239*758e9fbaSOystein Eftevaagif __name__ == '__main__': 240*758e9fbaSOystein Eftevaag main() 241