blob: ce9051f43a38aa010329f698289d5f10b42a54a0 [file] [log] [blame]
Karl Zhang3de5ab12021-05-31 11:45:48 +08001/*
2 * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8#ifndef TF_FUZZ_HPP
9#define TF_FUZZ_HPP
10
11#include <string>
12#include <vector>
13#include <iostream>
14#include <fstream>
15
16
17/* This project's header files #including other project headers quickly becomes
18 unrealistically complicated. The only solution is for each .cpp to include
19 the headers it needs.
20#include "psa_call.hpp"
21#include "sst_asset.hpp"
22#include "crypto_asset.hpp"
23#include "boilerplate.hpp"
24*/
25
26/* Shortcuts, to reduce code clutter, and reduce risk of coding errors. */
27#define IVM(content) if(rsrc->verbose_mode){content} // IVM = "If Verbose Mode"
28#define IV(content) if(verbose_mode){content} // Same, but for use by tf_fuzz methods
29
30
31// consts to help readability:
32const bool add_to_end = true; // add a call to the end of the call vector
33const bool add_random_after_barrier = false;
34 /* add to the call list randomly after the latest barrier for this asset, and
35 as late as the end of the list. */
36const bool yes_set_barrier = true; // create the call and set a barrier for that asset
37const bool dont_set_barrier = false;
38 // inserted call does not preclude calls related to that asset being placed earlier
39
40using namespace std;
41
42// class tf_fuzz_info mostly just groups together everything needed generate the test.
43class tf_fuzz_info
44{
45 /* In creating a test, TF-Fuzz parses the test template, creating a vector of
46 PSA-call-tracker objects. TF-Fuzz then performs a simulation of those calls
47 -- simulation only in enough detail to predict expected results of those PSA
48 calls. After that simulation phase, write_test() writes it all out. The
49 process of creating these structures also requires the boilerplate text
50 strings. */
51
52public:
53 // Data members (this class is mostly just to group stuff together, so public):
54 vector<string> prep_code; // variable declarations to write out to test file
55 vector<psa_call*> calls;
56 /* the calls to perform: Note: must be vector *psa_call; a vector of
57 psa_call does not allow (run-time) polymorphism. */
58 boilerplate *bplate; // the boilerplate text for building the test
59 gibberish gibbergen; // the gibberish asset-data generator
60 crc32 hashgen; // simple 32-bit LFSR-based hashing generator
61 /* Note: The following asset-lists are kept in base-class type to allow a
62 common template-line processing function in tf_fuzz_grammar.y. */
63 vector<psa_asset*> active_sst_asset; // list of known and usable SST assets
64 vector<psa_asset*> deleted_sst_asset; // deleted SST assets
65 vector<psa_asset*> invalid_sst_asset; // SST assets with invalid attributes
66 vector<psa_asset*> active_key_asset; // list of known and usable keys
67 vector<psa_asset*> deleted_key_asset; // deleted keys
68 vector<psa_asset*> invalid_key_asset; // keys with invalid attributes
69 vector<psa_asset*> active_policy_asset; // list of known, usable policies
70 vector<psa_asset*> deleted_policy_asset; // deleted policies
71 vector<psa_asset*> invalid_policy_asset; // policies with invalid attrs
72 /* The "variable" vector tracks variables in the generated code. Actually,
73 it tracks variables explicitly named in the test template, and actual-data
74 holder variables from reading an asset. It does not track asset set-data
75 or asset expect-data variables, because there are multiple versions of
76 those, and it's easier to just to "count off" those multiple versions.
77 Notice that, unlike the above vectors, the variable vector is not a
78 vector of pointers to variable_info objects, but of the objects themselves.
79 This is because polymorphism is not of concern here. */
80 vector<variable_info> variable;
81 string test_purpose; // what the test tests
82 long rand_seed; // the original random seed, whether passed in or defaulted
83 string template_file_name, test_output_file_name;
84 FILE *template_file;
85 /* handle to the test-template input file. Unfortunately I can't seem to
86 get lex/yacc to understand C++ file references, probably because I'm
87 "extern C"ing the Lex content (Yacc/Bison turns out to be a lot easier
88 to coerce into generating C++ code than (F)Lex). */
89 ofstream output_C_file; // handle to the output C test file
90 bool verbose_mode; // true to "think aloud"
91 bool include_hashing_code; // true to instantiate the hashing code
92 // Methods:
93 asset_search find_or_create_sst_asset (
94 psa_asset_search criterion, // what to search on
95 psa_asset_usage where, // where to search
96 string target_name, // ignored if not searching on name
97 uint64_t target_id, // ignored if not searching on ID (e.g., SST UID)
98 long &serial_no, // search by asset's unique serial number
99 bool create_asset, // true to create the asset if it doesn't exist
100 vector<psa_asset*>::iterator &asset // returns a pointer to asset
101 );
102 asset_search find_or_create_key_asset (
103 psa_asset_search criterion, // what to search on
104 psa_asset_usage where, // where to search
105 string target_name, // ignored if not searching on name
106 uint64_t target_id, // ignored if not searching on ID (e.g., SST UID)
107 long &serial_no, // search by asset's unique serial number
108 bool create_asset, // true to create the asset if it doesn't exist
109 vector<psa_asset*>:: iterator &asset // returns iterator to asset
110 );
111 asset_search find_or_create_policy_asset (
112 psa_asset_search criterion, // what to search on
113 psa_asset_usage where, // where to search
114 string target_name, // ignored if not searching on name
115 uint64_t target_id, // also ignored if not searching on ID (e.g., SST UID)
116 long &serial_no, // search by asset's unique serial number
117 bool create_asset, // true to create the asset if it doesn't exist
118 vector<psa_asset*>::iterator &asset // returns iterator to asset
119 );
120 asset_search find_or_create_psa_asset (
121 psa_asset_type asset_type, // what type of asset to find
122 psa_asset_search criterion, // what to search on
123 psa_asset_usage where, // where to search
124 string target_name, // ignored if not searching on name
125 uint64_t target_id, // also ignored if not searching on ID (e.g., SST UID)
126 long &serial_no, // search by asset's unique serial number
127 bool create_asset, // true to create the asset if it doesn't exist
128 vector<psa_asset*>::iterator &asset // returns iterator to asset
129 );
130 vector<variable_info>::iterator find_var (string var_name);
131 void parse_cmd_line_params (int argc, char* argv[]);
132 // parse command-line parameters, and open files
133 void add_call (psa_call *the_call, bool to_end, bool set_barrier_bool);
134 /* stuffs a new call into the call list, either sequentially or at a random
135 place after a "barrier" for that particular asset. If set_barrier_bool
136 is true, it will prevent calls related to this asset from going before
137 this call. */
138 bool make_var (string var_name);
139 void simulate_calls (void);
140 // goes through generated calls calculating expected results
141 void write_test (void); // writes out the test's .c file
142 void teardown_test(void); // removes any PSA resources used in the test
143 tf_fuzz_info (void); // (constructor)
144 ~tf_fuzz_info (void);
145
146protected:
147 // Data members:
148 vector<string> teardown_calls;
149 // list of PSA commands to remove assets left over upon test completion
150 // Methods:
151
152private:
153 // Data members:
154 // Methods:
155};
156
157
158/*--------------------------------------------------------------
159 Helper functions:
160--------------------------------------------------------------*/
161
162
163template<typename CALL_TYPE>
164void define_call (set_data_info set_data, bool random_data, bool fill_in_template,
165 bool create_call, template_line *temLin, tf_fuzz_info *rsrc,
166 bool to_end_bool, bool set_barrier_bool) {
167 CALL_TYPE *the_call;
168 gibberish gib;
169 char gib_buff[1000];
170 string t_string;
171
172 if (fill_in_template) {
173 if (set_data.literal_data_not_file) {
174 if (random_data) {
175 int rand_data_length = 12 + (rand() % 800);
176 gib.sentence (gib_buff, gib_buff + rand_data_length - 1);
177 t_string = gib_buff;
178 temLin->set_data.set_calculated (t_string);
179 }
180 } else {
181 if (set_data.file_path == "") { // catch the most likely failure at least!
182 cerr << "Error: Tool-internal: Please report error "
183 << "#407 to the TF-Fuzz developers." << endl;
184 exit(407);
185 }
186 temLin->set_data.set_file (set_data.file_path);
187 // set in sst_asset_make_file_path
188 }
189 }
190 if (create_call) {
191 the_call = new CALL_TYPE (rsrc, temLin->call_ser_no,
192 temLin->asset_info.how_asset_found);
193 if (!temLin->copy_template_to_call (the_call)) {
194 cerr << "Error: Tool-internal: Please report error "
195 << "#402 to the TF-Fuzz developers." << endl;
196 exit(402);
197 }
198 rsrc->add_call (the_call, to_end_bool, set_barrier_bool);
199 }
200}
201
202#endif // #ifndef TF_FUZZ_HPP