blob: ce9051f43a38aa010329f698289d5f10b42a54a0 [file] [log] [blame]
/*
* Copyright (c) 2019-2020, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef TF_FUZZ_HPP
#define TF_FUZZ_HPP
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
/* This project's header files #including other project headers quickly becomes
unrealistically complicated. The only solution is for each .cpp to include
the headers it needs.
#include "psa_call.hpp"
#include "sst_asset.hpp"
#include "crypto_asset.hpp"
#include "boilerplate.hpp"
*/
/* Shortcuts, to reduce code clutter, and reduce risk of coding errors. */
#define IVM(content) if(rsrc->verbose_mode){content} // IVM = "If Verbose Mode"
#define IV(content) if(verbose_mode){content} // Same, but for use by tf_fuzz methods
// consts to help readability:
const bool add_to_end = true; // add a call to the end of the call vector
const bool add_random_after_barrier = false;
/* add to the call list randomly after the latest barrier for this asset, and
as late as the end of the list. */
const bool yes_set_barrier = true; // create the call and set a barrier for that asset
const bool dont_set_barrier = false;
// inserted call does not preclude calls related to that asset being placed earlier
using namespace std;
// class tf_fuzz_info mostly just groups together everything needed generate the test.
class tf_fuzz_info
{
/* In creating a test, TF-Fuzz parses the test template, creating a vector of
PSA-call-tracker objects. TF-Fuzz then performs a simulation of those calls
-- simulation only in enough detail to predict expected results of those PSA
calls. After that simulation phase, write_test() writes it all out. The
process of creating these structures also requires the boilerplate text
strings. */
public:
// Data members (this class is mostly just to group stuff together, so public):
vector<string> prep_code; // variable declarations to write out to test file
vector<psa_call*> calls;
/* the calls to perform: Note: must be vector *psa_call; a vector of
psa_call does not allow (run-time) polymorphism. */
boilerplate *bplate; // the boilerplate text for building the test
gibberish gibbergen; // the gibberish asset-data generator
crc32 hashgen; // simple 32-bit LFSR-based hashing generator
/* Note: The following asset-lists are kept in base-class type to allow a
common template-line processing function in tf_fuzz_grammar.y. */
vector<psa_asset*> active_sst_asset; // list of known and usable SST assets
vector<psa_asset*> deleted_sst_asset; // deleted SST assets
vector<psa_asset*> invalid_sst_asset; // SST assets with invalid attributes
vector<psa_asset*> active_key_asset; // list of known and usable keys
vector<psa_asset*> deleted_key_asset; // deleted keys
vector<psa_asset*> invalid_key_asset; // keys with invalid attributes
vector<psa_asset*> active_policy_asset; // list of known, usable policies
vector<psa_asset*> deleted_policy_asset; // deleted policies
vector<psa_asset*> invalid_policy_asset; // policies with invalid attrs
/* The "variable" vector tracks variables in the generated code. Actually,
it tracks variables explicitly named in the test template, and actual-data
holder variables from reading an asset. It does not track asset set-data
or asset expect-data variables, because there are multiple versions of
those, and it's easier to just to "count off" those multiple versions.
Notice that, unlike the above vectors, the variable vector is not a
vector of pointers to variable_info objects, but of the objects themselves.
This is because polymorphism is not of concern here. */
vector<variable_info> variable;
string test_purpose; // what the test tests
long rand_seed; // the original random seed, whether passed in or defaulted
string template_file_name, test_output_file_name;
FILE *template_file;
/* handle to the test-template input file. Unfortunately I can't seem to
get lex/yacc to understand C++ file references, probably because I'm
"extern C"ing the Lex content (Yacc/Bison turns out to be a lot easier
to coerce into generating C++ code than (F)Lex). */
ofstream output_C_file; // handle to the output C test file
bool verbose_mode; // true to "think aloud"
bool include_hashing_code; // true to instantiate the hashing code
// Methods:
asset_search find_or_create_sst_asset (
psa_asset_search criterion, // what to search on
psa_asset_usage where, // where to search
string target_name, // ignored if not searching on name
uint64_t target_id, // ignored if not searching on ID (e.g., SST UID)
long &serial_no, // search by asset's unique serial number
bool create_asset, // true to create the asset if it doesn't exist
vector<psa_asset*>::iterator &asset // returns a pointer to asset
);
asset_search find_or_create_key_asset (
psa_asset_search criterion, // what to search on
psa_asset_usage where, // where to search
string target_name, // ignored if not searching on name
uint64_t target_id, // ignored if not searching on ID (e.g., SST UID)
long &serial_no, // search by asset's unique serial number
bool create_asset, // true to create the asset if it doesn't exist
vector<psa_asset*>:: iterator &asset // returns iterator to asset
);
asset_search find_or_create_policy_asset (
psa_asset_search criterion, // what to search on
psa_asset_usage where, // where to search
string target_name, // ignored if not searching on name
uint64_t target_id, // also ignored if not searching on ID (e.g., SST UID)
long &serial_no, // search by asset's unique serial number
bool create_asset, // true to create the asset if it doesn't exist
vector<psa_asset*>::iterator &asset // returns iterator to asset
);
asset_search find_or_create_psa_asset (
psa_asset_type asset_type, // what type of asset to find
psa_asset_search criterion, // what to search on
psa_asset_usage where, // where to search
string target_name, // ignored if not searching on name
uint64_t target_id, // also ignored if not searching on ID (e.g., SST UID)
long &serial_no, // search by asset's unique serial number
bool create_asset, // true to create the asset if it doesn't exist
vector<psa_asset*>::iterator &asset // returns iterator to asset
);
vector<variable_info>::iterator find_var (string var_name);
void parse_cmd_line_params (int argc, char* argv[]);
// parse command-line parameters, and open files
void add_call (psa_call *the_call, bool to_end, bool set_barrier_bool);
/* stuffs a new call into the call list, either sequentially or at a random
place after a "barrier" for that particular asset. If set_barrier_bool
is true, it will prevent calls related to this asset from going before
this call. */
bool make_var (string var_name);
void simulate_calls (void);
// goes through generated calls calculating expected results
void write_test (void); // writes out the test's .c file
void teardown_test(void); // removes any PSA resources used in the test
tf_fuzz_info (void); // (constructor)
~tf_fuzz_info (void);
protected:
// Data members:
vector<string> teardown_calls;
// list of PSA commands to remove assets left over upon test completion
// Methods:
private:
// Data members:
// Methods:
};
/*--------------------------------------------------------------
Helper functions:
--------------------------------------------------------------*/
template<typename CALL_TYPE>
void define_call (set_data_info set_data, bool random_data, bool fill_in_template,
bool create_call, template_line *temLin, tf_fuzz_info *rsrc,
bool to_end_bool, bool set_barrier_bool) {
CALL_TYPE *the_call;
gibberish gib;
char gib_buff[1000];
string t_string;
if (fill_in_template) {
if (set_data.literal_data_not_file) {
if (random_data) {
int rand_data_length = 12 + (rand() % 800);
gib.sentence (gib_buff, gib_buff + rand_data_length - 1);
t_string = gib_buff;
temLin->set_data.set_calculated (t_string);
}
} else {
if (set_data.file_path == "") { // catch the most likely failure at least!
cerr << "Error: Tool-internal: Please report error "
<< "#407 to the TF-Fuzz developers." << endl;
exit(407);
}
temLin->set_data.set_file (set_data.file_path);
// set in sst_asset_make_file_path
}
}
if (create_call) {
the_call = new CALL_TYPE (rsrc, temLin->call_ser_no,
temLin->asset_info.how_asset_found);
if (!temLin->copy_template_to_call (the_call)) {
cerr << "Error: Tool-internal: Please report error "
<< "#402 to the TF-Fuzz developers." << endl;
exit(402);
}
rsrc->add_call (the_call, to_end_bool, set_barrier_bool);
}
}
#endif // #ifndef TF_FUZZ_HPP