Initial check-in of TF-Fuzz.

Author:  Gary Morrison <gary.morrison@arm.com>
Signed-off-by:  Gary Morrison <gary.morrison@arm.com>

Change-Id: I8f739c3403bf2a2808f33c28910c7bda6aca7887
diff --git a/tools/tf_fuzz/tf_fuzz.hpp b/tools/tf_fuzz/tf_fuzz.hpp
new file mode 100644
index 0000000..7668998
--- /dev/null
+++ b/tools/tf_fuzz/tf_fuzz.hpp
@@ -0,0 +1,178 @@
+/*
+ * 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"
+*/
+
+using namespace std;
+
+/* class tf_fuzz_info mostly just groups together everything needed to gather, then
+   write out the test.  This, so that they can be passed into the parser. */
+
+class tf_fuzz_info
+{
+    /* In creating a test, TF-Fuzz collects together a vector of strings cataloging
+       data structures used by PSA commands, and a vector of PSA call objects.  Once
+       the template is completely parsed, write_test() writes it all out.  The
+       process of creating these structures also requires the boilerplate text
+       strings.  In the process of building the test, it must track PSA assets to
+       "model" expected results of calls. */
+
+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
+        string test_purpose;  // one text substitution to be performed at the top level
+        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,  // 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_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
+        );
+        void teardown_test(void);  // removes any PSA resources used in the test
+        void write_test (void);  // returns success==true, fail==false
+        void parse_cmd_line_params (int argc, char* argv[]);
+            // parse command-line parameters, and open files
+        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
+) {
+    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 = 10 + (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) {
+        if (temLin->how_asset_found == asset_search::unsuccessful) {
+            cerr << "Error:  Tool-internal:  Please report error "
+                 << "#401 to the TF-Fuzz developers." << endl;
+            exit(401);
+        }
+        the_call = new CALL_TYPE (rsrc, temLin->call_ser_no,
+                                  temLin->how_asset_found);
+        rsrc->calls.push_back(the_call);  /* (note: this is not a memory leak!) */
+        temLin->copy_template_to_asset();
+        if (!temLin->copy_template_to_call()) {
+            cerr << "Error:  Tool-internal:  Please report error "
+                 << "#402 to the TF-Fuzz developers." << endl;
+            exit(402);
+        }
+    }
+}
+
+#endif  // #ifndef TF_FUZZ_HPP