Add tf_fuzz tool
This is fully derived from tf-m repo.
Signed-off-by: Karl Zhang <karl.zhang@arm.com>
Change-Id: I8d35e70eda9081af66d8fa3f3cb4beb1d953060e
diff --git a/tf_fuzz/utility/README b/tf_fuzz/utility/README
new file mode 100644
index 0000000..5285fff
--- /dev/null
+++ b/tf_fuzz/utility/README
@@ -0,0 +1,11 @@
+As its name implies, this .../tf_fuzz/utility directory just contains
+various utility-compute code.
+
+
+For more information, please browse to:
+
+ https://ci.trustedfirmware.org/job/tf-m-build-test-nightly/lastSuccessfulBuild/artifact/build-docs/tf-m_documents/install/doc/user_guide/html/docs/user_guides/tf_fuzz/utility_dir.html
+
+--------------
+
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
diff --git a/tf_fuzz/utility/compute.cpp b/tf_fuzz/utility/compute.cpp
new file mode 100644
index 0000000..708a1f3
--- /dev/null
+++ b/tf_fuzz/utility/compute.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <cstdint> // for uint32_t
+#include "compute.hpp"
+
+
+using namespace std;
+
+/**********************************************************************************
+ Methods of class crc32 follow:
+**********************************************************************************/
+
+crc32::crc32 (void)
+{
+ shift_reg = 0x55555555; // just give it some default value
+}
+
+void crc32::seed_lfsr (uint32_t init_value)
+{
+ shift_reg = init_value;
+}
+
+/* lfsr_1b() performs one shift of the LFSR, factoring in a single bit of info,
+ that single bit must be in the low-order bit of the parameter. It returns
+ the LFSR value, which may be ignored. */
+uint32_t crc32::lfsr_1b (uint32_t a_bit)
+{
+ bool odd;
+
+ odd = ((shift_reg ^ a_bit) & 1) == 1;
+ shift_reg >>= 1;
+ if (odd) {
+ shift_reg ^= polynomial;
+ }
+ if (shift_reg == 0) {
+ // Theoretically should never happen, but precaution...
+ seed_lfsr (0x55555555);
+ }
+ return shift_reg;
+}
+
+uint32_t crc32::crc (uint8_t a_byte)
+{
+ for (int i = 0; i < 8; i++) {
+ lfsr_1b ((uint32_t) a_byte);
+ a_byte >>= 1;
+ }
+ return shift_reg;
+}
+
+uint32_t crc32::crc (uint16_t a_halfword)
+{
+ for (int i = 0; i < 16; i++) {
+ lfsr_1b ((uint32_t) a_halfword);
+ a_halfword >>= 1;
+ }
+ return shift_reg;
+}
+
+uint32_t crc32::crc (uint32_t a_word)
+{
+ for (int i = 0; i < 32; i++) {
+ lfsr_1b ((uint32_t) a_word);
+ a_word >>= 1;
+ }
+ return shift_reg;
+}
+
+/**********************************************************************************
+ End of methods of class crc32.
+**********************************************************************************/
diff --git a/tf_fuzz/utility/compute.hpp b/tf_fuzz/utility/compute.hpp
new file mode 100644
index 0000000..c6ece6c
--- /dev/null
+++ b/tf_fuzz/utility/compute.hpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef COMPUTE_HPP
+#define COMPUTE_HPP
+
+#include <cstdlib>
+
+using namespace std;
+
+/* Arguably at least, this LFSR-based hashing code is run more commonly on the
+ target itself -- included in the generated code -- than it is run here.
+ However, it's available here too, such as to parallel-calculate expected hash
+ values. */
+
+class crc32
+{
+public:
+ void seed_lfsr (uint32_t init_value);
+ /* lfsr_1b() performs one shift of the LFSR, factoring in a single bit of info,
+ that single bit must be in the low-order bit of the parameter. */
+ uint32_t lfsr_1b (uint32_t a_bit);
+ // crc() has two overloadings, calculating the CRC for byte or word quantities:
+ uint32_t crc (uint8_t a_byte);
+ uint32_t crc (uint16_t a_halfword);
+ uint32_t crc (uint32_t a_word);
+ crc32 (void);
+private:
+ const uint32_t polynomial = 0xb4bcd35c;
+ uint32_t shift_reg;
+};
+
+#endif /* COMPUTE_HPP */
diff --git a/tf_fuzz/utility/compute.o b/tf_fuzz/utility/compute.o
new file mode 100644
index 0000000..ee4e580
--- /dev/null
+++ b/tf_fuzz/utility/compute.o
Binary files differ
diff --git a/tf_fuzz/utility/data_blocks.cpp b/tf_fuzz/utility/data_blocks.cpp
new file mode 100644
index 0000000..09a25e9
--- /dev/null
+++ b/tf_fuzz/utility/data_blocks.cpp
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/* These classes "cut down the clutter" by grouping together related data and
+ associated methods (most importantly their constructors) used in template_
+ line, psa_call, psa_asset (etc.). */
+
+#include <string>
+#include <vector>
+#include <cstdint>
+
+#include "class_forwards.hpp"
+
+#include "boilerplate.hpp"
+#include "randomization.hpp"
+#include "gibberish.hpp"
+#include "compute.hpp"
+#include "string_ops.hpp"
+#include "data_blocks.hpp"
+#include "psa_asset.hpp"
+#include "crypto_asset.hpp"
+#include "find_or_create_asset.hpp"
+#include "psa_call.hpp"
+#include "template_line.hpp"
+#include "tf_fuzz.hpp"
+
+
+
+/**********************************************************************************
+ Methods of class expect_info follow:
+**********************************************************************************/
+
+expect_info::expect_info (void) // (default constructor)
+{
+ pf_nothing = false; // by default, TF-Fuzz provides expected results
+ pf_pass = pf_fail = pf_specified = false;
+ pf_result_string.assign (""); data.assign ("");
+ data_var_specified = false;
+ data_var.assign (""); // name of expected-data variable
+ data_specified = false;
+ data_matches_asset = false;
+ data.assign ("");
+ pf_info_incomplete = true;
+ n_exp_vars = -1; // so the first reference is 0 (no suffix), then _1, _2, ...
+ expected_results_saved = false;
+}
+expect_info::~expect_info (void) // (destructor)
+{}
+
+void expect_info::set_pf_pass (void)
+{
+ pf_pass = true;
+ pf_fail = pf_nothing = pf_specified = false;
+ pf_result_string = "";
+}
+
+void expect_info::set_pf_fail (void)
+{
+ pf_fail = true;
+ pf_pass = pf_nothing = pf_specified = false;
+ pf_result_string = "";
+}
+
+void expect_info::set_pf_nothing (void)
+{
+ pf_nothing = true;
+ pf_fail = pf_pass = pf_specified = false;
+ pf_result_string = "";
+}
+
+void expect_info::set_pf_error (string error)
+{
+ pf_specified = true;
+ pf_result_string.assign (error); // just default "guess," to be filled in
+ pf_pass = pf_fail = pf_nothing = false;
+}
+
+/* The expected pass/fail results are not available from the parser until the call has
+ already been created. The flag, pf_info_incomplete, that indicates whether or not
+ the "expects" information has been filled in. If not, fill it in from the template,
+ once that info has been parsed. */
+void expect_info::copy_expect_to_call (psa_call *the_call)
+{
+ the_call->exp_data.pf_nothing = pf_nothing;
+ the_call->exp_data.pf_pass = pf_pass;
+ the_call->exp_data.pf_fail = pf_fail;
+ the_call->exp_data.pf_specified = pf_specified;
+ the_call->exp_data.pf_result_string = pf_result_string;
+ the_call->exp_data.expected_results_saved = true;
+ the_call->exp_data.pf_info_incomplete = false;
+}
+
+/**********************************************************************************
+ End of methods of class expect_info.
+**********************************************************************************/
+
+
+/**********************************************************************************
+ Class set_data_info methods regarding setting and getting asset-data values:
+**********************************************************************************/
+
+string set_data_info::rand_creation_flags (void)
+{
+ return ((rand() % 2) == 1)?
+ "PSA_STORAGE_FLAG_WRITE_ONCE" : "PSA_STORAGE_FLAG_NONE";
+
+ /* TODO: There are also PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION and
+ PSA_STORAGE_FLAG_NO_CONFIDENTIALITY, but they don't seem to appear
+ in any test suites, so it's iffy as to whether they really exist.
+ We'll not routinely initialize to them, for now at least, but if
+ we want to enable them, then uncomment the following:
+ string result = "";
+ const int most_flags = 2,
+ int n_flags = (rand() % most_flags);
+
+ for (int i = 0; i < ; i < n_flags; ++i) {
+ switch (rand() % 4) {
+ case 0:
+ result += "PSA_STORAGE_FLAG_NONE";
+ break;
+ case 1:
+ result += "PSA_STORAGE_FLAG_WRITE_ONCE";
+ break;
+ case 2:
+ result += "PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION";
+ break;
+ case 3:
+ result += "PSA_STORAGE_FLAG_NO_CONFIDENTIALITY";
+ break;
+ }
+ if (i < n_flags-1)
+ result += " | ";
+ }
+ if (result == "") result = "PSA_STORAGE_FLAG_NONE";
+*/
+}
+
+set_data_info::set_data_info (void) // (default constructor)
+{
+ literal_data_not_file = true; // currently, not using files as data sources
+ string_specified = false;
+ data.assign ("");
+ random_data = false;
+ file_specified = false;
+ file_path.assign ("");
+ n_set_vars = -1; // so the first reference is 0 (no suffix), then _1, _2, ...
+ data_offset = 0;
+ flags_string = rand_creation_flags();
+}
+set_data_info::~set_data_info (void) // (destructor)
+{}
+
+/* set() establishes:
+ * An asset's data value from a template line (e.g., set sst snort data "data
+ value"), and
+ * *That* such a value was directly specified, as opposed to no data value having
+ been specified, or a random data value being requested.
+ Arguably, this method "has side effects," in that it not only sets a value, but
+ also "takes notes" about where that value came from.
+*/
+void set_data_info::set (string set_val)
+{
+ literal_data_not_file = true; // currently, not using files as data sources
+ string_specified = true;
+ data.assign (set_val);
+}
+
+/* set_calculated() establishes:
+ * An asset's data value as *not* taken from a template line, and
+ * *That* such a value was not directly specified in any template line, such as
+ if a random data value being requested.
+ Arguably, this method "has side effects," in that it not only sets a value, but
+ also "takes notes" about where that value came from.
+*/
+void set_data_info::set_calculated (string set_val)
+{
+ literal_data_not_file = true; // currently, not using files as data sources
+ string_specified = false;
+ data.assign (set_val);
+}
+
+/* randomize() establishes:
+ * An asset's data value as *not* taken from a template line, and
+ * *That* such a value was randomized.
+ Arguably, this method "has side effects," in that it not only sets a value, but
+ also "takes notes" about where that value came from.
+*/
+void set_data_info::randomize (void)
+{
+ gibberish gib;
+ char gib_buff[4096]; // spew gibberish into here
+ int rand_data_length = 0;
+
+ string_specified = false;
+ random_data = true;
+ literal_data_not_file = true;
+ rand_data_length = 40 + (rand() % 256);
+ /* Note: Multiple assets do get different random data */
+ gib.sentence (gib_buff, gib_buff + rand_data_length - 1);
+ data = gib_buff;
+}
+
+/* Getter for protected member, data. Protected so that it can only be set by
+ set() or set_calculated(), above, to establish not only its value but
+ how it came about. */
+string set_data_info::get (void)
+{
+ return data;
+}
+
+/* Currently, files as data sources aren't used, so this whole method is not "of
+ use," but that might change at some point. */
+bool set_data_info::set_file (string file_name)
+{
+ literal_data_not_file = true;
+ string_specified = false;
+ data.assign ("");
+ file_specified = true;
+ // Remove the ' ' quotes around the file name:
+ file_name.erase (0, 1);
+ file_name.erase (file_name.length()-1, 1);
+ file_path = file_name;
+ return true;
+}
+
+/**********************************************************************************
+ End of methods of class set_data_info.
+**********************************************************************************/
+
+
+/**********************************************************************************
+ Class asset_name_id_info methods regarding setting and getting asset-data values:
+**********************************************************************************/
+
+asset_name_id_info::asset_name_id_info (void) // (default constructor)
+{
+ id_n_not_name = false; // (arbitrary)
+ id_n = 100LL + ((uint64_t) rand() % 10000); // default to random ID#
+ asset_name.assign ("");
+ id_n_specified = name_specified = false; // no ID info yet
+ asset_type = psa_asset_type::unknown;
+ how_asset_found = asset_search::not_found;
+ the_asset = nullptr;
+ asset_ser_no = -1;
+}
+asset_name_id_info::~asset_name_id_info (void)
+{
+ asset_name_vector.clear();
+ asset_id_n_vector.clear();
+}
+
+/* set_name() establishes:
+ * An asset's "human" name from a template line, and
+ * *That* that name was directly specified, as opposed to the asset being defined
+ by ID only, or a random name being requested.
+ Arguably, this method "has side effects," in that it not only sets a name, but
+ also "takes notes" about where that name came from.
+*/
+void asset_name_id_info::set_name (string set_val)
+{
+ /* Use this to set the name as specified in the template file. Call this only
+ if the template file does indeed define a name. */
+ name_specified = true;
+ asset_name.assign (set_val);
+}
+
+/* set_calc_name() establishes:
+ * An asset's "human" name *not* from a template line, and
+ * *That* that name was *not* directly specified in any template line.
+ Arguably, this method "has side effects," in that it not only sets a name, but
+ also "takes notes" about where that name came from.
+*/
+void asset_name_id_info::set_calc_name (string set_val)
+{
+ name_specified = false;
+ asset_name.assign (set_val);
+}
+
+// set_just_name() sets an asset's "human" name, without noting how that name came up.
+void asset_name_id_info::set_just_name (string set_val)
+{
+ asset_name.assign (set_val);
+}
+
+/* Getter for protected member, asset_name. Protected so that it can only be set by
+ set_name() or set_calc_name(), above, to establish not only its value but
+ how it came about. */
+string asset_name_id_info::get_name (void)
+{
+ return asset_name;
+}
+
+// Asset IDs can be set directly from a uint64_t or converted from a string:
+void asset_name_id_info::set_id_n (string set_val)
+{
+ id_n = stol (set_val, 0, 0);
+}
+void asset_name_id_info::set_id_n (uint64_t set_val)
+{
+ id_n = set_val;
+}
+
+// Create ID-based name:
+string asset_name_id_info::make_id_n_based_name (uint64_t id_n)
+{
+ string result;
+
+ switch (asset_type) {
+ case psa_asset_type::sst:
+ result = "SST_ID_";
+ break;
+ case psa_asset_type::key:
+ result = "Key_ID_";
+ break;
+ case psa_asset_type::policy:
+ result = "Policy_ID_";
+ break;
+ default:
+ cerr << "\nError: Tool-internal: Please report error "
+ << "#1223 to the TF-Fuzz developers." << endl;
+ exit(1223);
+ }
+ result.append(to_string(id_n));
+ return result;
+}
+
+/**********************************************************************************
+ End of methods of class asset_name_id_info.
+**********************************************************************************/
+
+
+/**********************************************************************************
+ Class key_policy_info methods:
+**********************************************************************************/
+
+key_policy_info::key_policy_info (void) // (default constructor)
+{
+ get_policy_from_key = false; // specify policy asset by a key that uses it.
+ copy_key = false; // not copying one key to another
+ /* The following settings are not necessarily being randomized in mutually-
+ consistent ways, for two reasons: First, the template should set all that
+ matter, and second, testing TF response to nonsensical settings is also
+ valuable. */
+ exportable = (rand()%2==1? true : false);
+ copyable = (rand()%2==1? true : false);
+ can_encrypt = (rand()%2==1? true : false);
+ can_decrypt = (rand()%2==1? true : false);
+ can_sign = (rand()%2==1? true : false);
+ can_verify = (rand()%2==1? true : false);
+ derivable = (rand()%2==1? true : false);
+ persistent = (rand()%2==1? true : false);
+ // There's a really huge number of possible key types; won't randomize all:
+ key_type = rand_key_type();
+ usage_string.assign ("");
+ print_usage_true_string.assign ("");
+ print_usage_false_string.assign ("");
+ key_algorithm = rand_key_algorithm();
+ n_bits = 55 + (rand() % 1000);
+ gibberish *gib = new gibberish;
+ char buffer[256];
+ char *end;
+ int buf_len = 5ULL + (uint64_t) (rand() % 10);
+ end = gib->word (false, buffer, buffer + buf_len);
+ *end = '\0';
+ buffer[buf_len] = '\0';
+ handle_str = buffer;
+ gib->sentence (buffer, buffer + (40ULL + (uint64_t) (rand() % 200)));
+ key_data = buffer;
+ delete gib;
+}
+key_policy_info::~key_policy_info (void) // (destructor)
+{
+ return; // (even if only to have something to pin a breakpoint on)
+}
+
+
+/**********************************************************************************
+ End of methods of class key_policy_info.
+**********************************************************************************/
diff --git a/tf_fuzz/utility/data_blocks.hpp b/tf_fuzz/utility/data_blocks.hpp
new file mode 100644
index 0000000..f4628a5
--- /dev/null
+++ b/tf_fuzz/utility/data_blocks.hpp
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <string>
+
+/* These classes "cut down the clutter" by grouping together related data and
+ associated methods (most importantly their constructors) used in template_
+ line, psa_call, psa_asset (etc.). */
+
+#ifndef DATA_BLOCKS_HPP
+#define DATA_BLOCKS_HPP
+
+/* 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. However these in particular are mostly axiomatic: Not
+ dependent upon other classes. */
+
+
+using namespace std;
+
+
+/**********************************************************************************
+ Class expect_info is all about expected data and expected pass/fail information.
+ The members are therefore broken down with prefixes pf_ (for pass/fail) or
+ data_. Pass/fail, is broadly:
+ * "Pass" == the test passes
+ * "Specified" == some specified failure (e.g., no such asset)
+ * "Nothing" == no expectation
+ Expected data refers to psa-asset data values, generally after reading them.
+ Currently, they are limited to character strings, but that will probably be
+ generalized in the future.
+**********************************************************************************/
+
+class expect_info
+{
+public:
+ // Data members:
+ // Expected-result info:
+ bool pf_nothing; // true to not generate results-check(s)
+ bool pf_pass; // if !expect.pf_nothing, then pass is expected
+ bool pf_fail; // if "expect fail" was specified
+ bool pf_specified;
+ /* if !pf_nothing && !pf_pass, then
+ true == expected result was specified
+ false == tf_fuzz must model expected result, and
+ pf_result_string is the expected result */
+ string pf_result_string;
+ bool data_specified; // (literal expected data specified)
+ string data; // what test template expects data from reading an asset to be
+ int n_exp_vars; // how many check-value variables have been created
+ bool data_var_specified; // check against a variable
+ string data_var; // name of variable containing expected data
+ bool pf_info_incomplete;
+ /* In parsing the template, the expect information comes later than the
+ rest of the call info. This flag tells us to fill in the pass/fail
+ expect info when it comes available. */
+ bool expected_results_saved;
+ /* This indicates whether expected results have or have not already been
+ copied to this call. It's a "one-shot," so to speak, to copy only
+ once when results are known good. Since calls can be inserted into
+ earlier points in the call sequence (not always appended), the call
+ sequence has to be gone over for this process multiple times. */
+ // Methods:
+ expect_info (void); // (default constructor)
+ ~expect_info (void); // (destructor)
+ void set_pf_pass (void);
+ void set_pf_fail (void);
+ void set_pf_nothing (void);
+ void set_pf_error (string error);
+ void copy_expect_to_call (psa_call *the_call);
+
+protected:
+ // Data members:
+ bool data_matches_asset;
+ /* true if template specifies expected data, and that expected data
+ agrees with that in the asset */
+};
+
+
+/**********************************************************************************
+ Class set_data_info addresses PSA-asset data values as affected, directly or
+ indirctly/implicitly, by the template-line content. "Directly," that is, by
+ virtue of the template line stating verbatim what to set data to, or indirectly
+ by virtue of telling TF-Fuzz to create random data for it.
+**********************************************************************************/
+
+class set_data_info
+{
+public:
+ // Data members:
+ bool string_specified;
+ // true if a string of data is specified in template file
+ bool random_data; // true to generate random data for the asset
+ bool file_specified; // true if a file of expected data was specified
+ bool literal_data_not_file;
+ // true to use data strings rather than files as data source
+ int n_set_vars; // how many implicit set variables have been created
+ string file_path; // path to file, if specified
+ string flags_string;
+ // creation flags, nominally for SST but have to be in a vector of base-class
+ uint32_t data_offset; // offset into asset data
+ // Methods:
+ set_data_info (void); // (default constructor)
+ ~set_data_info (void); // (destructor)
+ void set (string set_val);
+ void set_calculated (string set_val);
+ void randomize (void);
+ string get (void);
+ bool set_file (string file_name);
+
+protected:
+ // Data members:
+ string data; // String describing asset data.
+ // Methods:
+ string rand_creation_flags (void);
+};
+
+
+/**********************************************************************************
+ Class asset_name_id_info groups together and acts upon all information related to the
+ human names (as reflected in the code variable names, etc.) for PSA assets.
+**********************************************************************************/
+
+class asset_name_id_info
+{
+public:
+ // Data members (not much value in "hiding" these behind getters)
+ psa_asset *the_asset;
+ psa_asset_type asset_type; // SST vs. key vs. policy (etc.)
+ bool id_n_not_name; // true to create a PSA asset by ID
+ bool name_specified; // true iff template supplied human name
+ bool id_n_specified; // true iff template supplied ID #
+ vector<string> asset_name_vector;
+ vector<int> asset_id_n_vector;
+ long asset_ser_no; // unique ID for psa asset needed to find data string
+ asset_search how_asset_found;
+ uint64_t id_n; // asset ID# (e.g., SST UID).
+ /* Note: This is just a holder to pass ID from template-line to call. The
+ IDs for a given template line are in asset_info.asset_id_n_vector. */
+ // Methods:
+ asset_name_id_info (void); // (default constructor)
+ ~asset_name_id_info (void); // (destructor)
+ void set_name (string set_val);
+ void set_calc_name (string set_val);
+ void set_just_name (string set_val);
+ string get_name (void);
+ void set_id_n (string set_val);
+ void set_id_n (uint64_t set_val);
+ string make_id_n_based_name (uint64_t id_n);
+ // create UID-based asset name
+
+protected:
+ // Data members:
+ string asset_name; // parsed from template, assigned to psa_asset object
+};
+
+
+/**********************************************************************************
+ Class key_policy_info collects together the aspects of a Crypto key attributes
+ ("policies"). These include aspects that can affect TF-Fuzz's test-generation.
+**********************************************************************************/
+
+class key_policy_info
+{
+public:
+ // Data members:
+ // Digested info:
+ bool get_policy_from_key;
+ /* if true, then we must get policy info from a stated key; the asset
+ here is a key that uses the policy, and not the policy itself. */
+ bool implicit_policy;
+ /* if true, then the key was defined with policy specifications, but not
+ a named policy, meaning that we have to create an implicit policy. */
+ bool copy_key; // true to indicate copying one key to another
+ bool exportable; // key data can be exported (viewed - fail exports if not).
+ bool copyable; // can be copied (fail key-copies if not).
+ bool can_encrypt; // OK for encryption (fail other uses).
+ bool can_decrypt; // OK for decryption (fail other uses).
+ bool can_sign; // OK for signing (fail other operations).
+ bool can_verify; // OK for verifing a message signature (fail other uses).
+ bool derivable; // OK for derive other keys (fail other uses).
+ bool persistent; // must be deleted at the end of test.
+ string usage_string;
+ /* This string is set to a PSA_KEY_USAGE_* value in the template
+ immediately prior to making define_call<add_policy_usage_call>.
+ The copy_template_to_call() therein sets the corresponding string
+ in the call, and that is copied into the code in the fill_in_command()
+ invocation. */
+ string print_usage_true_string;
+ /* For printing out policy usage, this states how to describe the usage
+ if it can be used this way. This is managed similarly with, and used
+ in conjunction with usage_string above. NOTE: THIS ALSO SERVES AS AN
+ INDICATOR WHETHER OR NOT TO PRINT ON A GET-USAGE CALL. "" means not
+ to print. */
+ string print_usage_false_string;
+ /* Also for printing out policy usage, this is how to describe usage if
+ it cannot be used this way. */
+ string key_type; // AES, DES, RSA pair, DS public, etc.
+ string key_algorithm;
+ int n_bits;
+ // for get_key_info call (possibly others) exected key size in bits
+ string handle_str; // the text name of the key's "handle"
+ string key_data; // the key data as best we can know it.
+ string asset_2_name;
+ // if there's a 2nd asset, such as policy on key call, this is its name
+ string asset_3_name; // if there's a 3rd asset, then this is its name
+
+ // Methods:
+ key_policy_info (void); // (default constructor)
+ ~key_policy_info (void); // (destructor)
+
+
+protected:
+ // Data members:
+ bool data_matches_asset;
+ /* true if template specifies expected data, and that expected data
+ agrees with that in the asset */
+};
+
+
+
+#endif // DATA_BLOCKS_HPP
+
diff --git a/tf_fuzz/utility/data_blocks.o b/tf_fuzz/utility/data_blocks.o
new file mode 100644
index 0000000..58a37a9
--- /dev/null
+++ b/tf_fuzz/utility/data_blocks.o
Binary files differ
diff --git a/tf_fuzz/utility/find_or_create_asset.hpp b/tf_fuzz/utility/find_or_create_asset.hpp
new file mode 100644
index 0000000..3daf37c
--- /dev/null
+++ b/tf_fuzz/utility/find_or_create_asset.hpp
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef FIND_OR_CREATE_ASSET_HPP
+#define FIND_OR_CREATE_ASSET_HPP
+
+using namespace std;
+
+/* This enum defines possible results when asked to find an existing, or create a
+ new PSA asset. */
+enum class asset_search
+{ found_active, // found as an actively-used asset
+ found_deleted, // found as a previously-used, but now-unusable asset
+ found_invalid, // found as a previously-used, but now-unusable asset
+ not_found, // if not found and if not allowed to create it
+ created_new, // no such existing asset was found so created new, active asset
+ unsuccessful, // ran out of memory or whatever
+ something_wrong // something wrong with the code; shouldn't happen
+};
+// Search areas:
+enum class psa_asset_usage // one particular area or all
+{ active, // found as an actively-used asset
+ deleted, // found as a previously-used, but now-unusable asset
+ invalid, // (invalid assets aren't completely defined yet)
+ all, // if not found and if not allowed to create it
+ none // just create it
+};
+// In searching for an asset, this enum specifies what to search for:
+enum class psa_asset_search
+{ name, // its human name
+ id, // its id, such as SST UID
+ serial // its serial number assigned upon creation
+};
+// Types of assets:
+enum class psa_asset_type
+{ sst, // (pretty obvious what each of these mean)
+ key,
+ policy,
+ unknown
+};
+
+
+// A few consts just to make code more readable:
+const bool yes_create_asset = true;
+const bool dont_create_asset = false;
+
+
+/* There are several variants, by asset type, of this method. So, C++ templating
+ is best. Note that, while the vectors are pointers to the base, psa_asset type,
+ the individual entries are all of the same ASSET_TYPE type. */
+template <typename ASSET_TYPE>
+asset_search generic_find_or_create_asset (
+ vector<psa_asset*> &active_asset_vector, // the three vectors of known assets
+ vector<psa_asset*> &deleted_asset_vector,
+ vector<psa_asset*> &invalid_asset_vector,
+ 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 on this if requested, but return serial regardless
+ bool create_asset, // true to create the asset if it doesn't exist
+ typename vector<psa_asset*>::iterator &asset
+ // returns iterator to the requested asset
+) {
+ ASSET_TYPE *new_asset;
+ bool match = false; // match found
+ // Look first in active assets:
+ if (where == psa_asset_usage::active || where == psa_asset_usage::all) {
+ for (auto as = active_asset_vector.begin(); as < active_asset_vector.end();
+ ++as) {
+ psa_asset *pass = *as;
+ switch (criterion) {
+ case psa_asset_search::name: // human-meaningful name
+ match = (pass->asset_info.get_name() == target_name);
+ break;
+ case psa_asset_search::id: // ID#
+ match = (pass->asset_info.id_n == target_id);
+ break;
+ default: // psa_asset_search::serial
+ match = (pass->asset_info.asset_ser_no == serial_no);
+ break;
+ }
+ if (match) {
+ asset = as;
+ return asset_search::found_active;
+ }
+ }
+ }
+ // Look then in deleted assets:
+ if (where == psa_asset_usage::deleted || where == psa_asset_usage::all) {
+ for (auto as = deleted_asset_vector.begin(); as < deleted_asset_vector.end();
+ ++as) {
+ psa_asset *pass = *as;
+ switch (criterion) {
+ case psa_asset_search::name: // human-meaningful name
+ match = (pass->asset_info.get_name() == target_name);
+ break;
+ case psa_asset_search::id: // ID#
+ match = (pass->asset_info.id_n == target_id);
+ break;
+ default: // psa_asset_search::serial
+ match = (pass->asset_info.asset_ser_no == serial_no);
+ break;
+ }
+ if (match) {
+ asset = as;
+ if (create_asset) {
+ /* Asset previously existed, but has since been removed. Resur-
+ rect it into active assets, but zap its data: */
+ pass->set_data.set("");
+ pass->exp_data.data.assign("");
+ deleted_asset_vector.erase (as);
+ active_asset_vector.push_back (pass);
+ return asset_search::found_active; // it's active now anyway...
+ } else {
+ return asset_search::found_deleted;
+ }
+ }
+ }
+ }
+ // Look then in invalid assets:
+ if (where == psa_asset_usage::invalid || where == psa_asset_usage::all) {
+ for (auto as = invalid_asset_vector.begin(); as < invalid_asset_vector.end();
+ ++as) {
+ psa_asset *pass = *as;
+ switch (criterion) {
+ case psa_asset_search::name: // human-meaningful name
+ match = (pass->asset_info.get_name() == target_name);
+ break;
+ case psa_asset_search::id: // ID#
+ match = (pass->asset_info.id_n == target_id);
+ break;
+ default: // psa_asset_search::serial
+ match = (pass->asset_info.asset_ser_no == serial_no);
+ break;
+ }
+ if (match) {
+ asset = as;
+ return asset_search::found_invalid;
+ }
+ }
+ }
+ // Couldn't find it in any of the existing lists, so create it in active assets:
+ if (create_asset) {
+ try {
+ new_asset = new ASSET_TYPE;
+ if (criterion == psa_asset_search::id) {
+ new_asset->asset_info.id_n = target_id;
+ } // TO DO: probably should do the same for its name in a name search!
+ active_asset_vector.push_back(new_asset);
+ asset = prev(active_asset_vector.end());
+ return asset_search::created_new;
+ }
+ catch (std::bad_alloc& bad) {
+ std::cerr << "Error: Failed to allocate an ASSET_TYPE: " << bad.what()
+ << endl;
+ return asset_search::unsuccessful;
+ }
+ } else {
+ return asset_search::not_found;
+ }
+ return asset_search::something_wrong; // should never get here
+}
+
+#endif // ifndef FIND_OR_CREATE_ASSET_HPP
diff --git a/tf_fuzz/utility/gibberish.cpp b/tf_fuzz/utility/gibberish.cpp
new file mode 100644
index 0000000..58a3f8f
--- /dev/null
+++ b/tf_fuzz/utility/gibberish.cpp
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/*
+ * These functions produce random-gibberish quasi-words in a quasi-sentence.
+ * Random character streams may be conceptually sufficient, but for testing
+ * purposes, it's much easier for humans to remember and to distinguish semi-
+ * pro-nounceable gibberish like "dokwab neltiegib..." than
+ * "f7H%r^&B*5|j6@Mz>\#...".
+ */
+
+#include <string>
+
+#include "gibberish.hpp" // shouldn't need any other project headers
+
+
+/**
+ * \brief Returns a letter for random-gibberish quasi-words in a quasi-sentence.
+ *
+ * \return A letter character value.
+ *
+ */
+char gibberish::letter(void)
+{
+ return 'a' + (rand() % ('z'-'a' + 1));
+}
+
+
+/**
+ * \brief Returns a vowel for random-gibberish quasi-words in a quasi-sentence.
+ *
+ * \return A vowel character value.
+ *
+ */
+char gibberish::vowel(void)
+{
+ char vowels[] = "aeiou";
+
+ return vowels[rand() % 5];
+}
+
+
+/**
+ * \brief Returns a consonant for random-gibberish quasi-words in a quasi-sentence.
+ *
+ * \return A consonant character value.
+ *
+ */
+char gibberish::consonant(void)
+{
+ char candidate;
+
+ do {
+ candidate = letter();
+ } while ( candidate == 'a' || candidate == 'e' || candidate == 'i'
+ || candidate == 'o' || candidate == 'u');
+ return candidate;
+}
+
+
+/**
+ * \brief Appends a semi-pronounceable syllable onto a string, stopping before
+ * the end of the string, for random-gibberish quasi-words in a
+ * quasi-sentence. Returns a pointer to the next open spot in the string.
+ *
+ * \param[in] string_ptr Pointer to where to put the word.
+ *
+ * \param[in] stop Pointer to last character in quasi-sentence.
+ *
+ * \return Pointer to first character after the word.
+ *
+ */
+char *gibberish::syllable (char *string_ptr, char *stop)
+{
+ char *parser; /* points into string while building it */
+
+ parser = string_ptr;
+ if ((rand() % 4) < 3) {
+ if (parser < stop) *parser++ = consonant();
+ if (parser < stop) *parser++ = vowel();
+ if (parser < stop) *parser++ = letter();
+ } else {
+ if (parser < stop) *parser++ = vowel();
+ if (((rand() % 4) < 1) && parser < stop) {
+ *parser++ = vowel();
+ }
+ if (parser < stop) *parser++ = consonant();
+ }
+ return parser;
+}
+
+
+/**
+ * \brief Appends a mostly-pronounceable quasi-word onto a quasi-sentence string,
+ * stopping before the end of the string. Returns a pointer to the next
+ * open spot in the string.
+ *
+ * \param[in] initial_cap: True if the first character should be capitalized.
+ *
+ * \param[in] string_ptr Pointer to where to put the word.
+ *
+ * \param[in] stop Pointer to last character in quasi-sentence.
+ *
+ * \return Pointer to first character after the word.
+ *
+ */
+char *gibberish::word (bool initial_cap, char *string_ptr, char *stop)
+{
+ int syllable_count;
+ char *parser; /* points into string while building it */
+ string avoid_check;
+ bool has_avoid_words;
+ do {
+ has_avoid_words = false;
+ for (syllable_count = 0, parser = string_ptr;
+ syllable_count < 4
+ && (rand() % 5) >= syllable_count
+ && parser < stop;
+ syllable_count++) {
+ parser = syllable (parser, stop);
+ }
+ for (int i = 0; i < n_avoids; i++) {
+ avoid_check = string_ptr;
+ if (avoid[i] == avoid_check) {
+ has_avoid_words = true;
+ break;
+ }
+ }
+ if (initial_cap) {
+ *string_ptr -= 'a' - 'A'; /* more or less assumes ASCII */
+ }
+ } while (has_avoid_words);
+ return parser;
+}
+
+
+/**
+ * \brief Creates a mostly-pronounceable, random-gibberish quasi-sentence,
+ * stopping before the end of the string.
+ *
+ * \param[in] string_ptr Pointer to beginning of string for quasi-sentence.
+ *
+ * \param[in] stop Pointer to last character in quasi-sentence.
+ *
+ */
+void gibberish::sentence (char *string_ptr, char *stop)
+{
+ char *parser; /* points into string while building it */
+ char punctuation[] = ".?!";
+
+ *stop = '\0'; /* null-terminate the string */
+ --stop;
+ parser = word (capitalize, string_ptr, stop);
+ if (parser < stop) {
+ *parser++ = ' ';
+ }
+ for (; parser < stop; ) {
+ parser = word (dont_capitalize, parser, stop);
+ if (parser < stop) {
+ *parser++ = ' ';
+ }
+ }
+ parser--;
+ if (*parser == ' ') {
+ *parser = vowel(); // just to not have a blank at the end
+ }
+ *stop = punctuation[rand() % 3];
+}
+
+
+/**
+ * \brief Chooses a gibberish-sentence length.
+ *
+ */
+int gibberish::pick_sentence_len (void)
+{
+ return min_literal_data_len + (rand() % literal_data_len_span);
+}
+
+
+/**
+ * \brief Constructor for gibberish object.
+ *
+ */
+gibberish::gibberish (void)
+{
+ string holder;
+
+ for (int i = 0; i < n_avoids; i++) {
+ holder = avoid[i];
+ for (long unsigned int j = 0; j < holder.length(); j++) {
+ holder[j] = holder[j] - 1;
+ }
+ avoid[i] = holder;
+ }
+}
+
+
+/**
+ * \brief Destructor for gibberish object.
+ *
+ */
+gibberish::~gibberish (void)
+{
+ // Nothing to tear down.
+}
diff --git a/tf_fuzz/utility/gibberish.hpp b/tf_fuzz/utility/gibberish.hpp
new file mode 100644
index 0000000..c5692e3
--- /dev/null
+++ b/tf_fuzz/utility/gibberish.hpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/*
+ * sec-regress.c&.h implement the Scripted-Call Application, and other functions
+ * for the security-regression testing feature.
+ *
+ */
+
+#ifndef GIBBERISH_HPP
+#define GIBBERISH_HPP
+
+#include <cstdlib>
+
+using namespace std;
+
+class gibberish
+{
+public: // not much value in hiding these behind getters and setters
+ // Data members:
+ static const int min_literal_data_len = 32, max_literal_data_len = 512,
+ literal_data_len_span = max_literal_data_len - min_literal_data_len;
+ // Methods:
+ gibberish (void); // (constructor)
+ ~gibberish (void);
+ char letter (void);
+ char vowel (void);
+ char consonant (void);
+ char *syllable (char *string_ptr, char *stop);
+ char *word (bool initial_cap, char *string_ptr, char *stop);
+ int pick_sentence_len (void);
+ void sentence (char *string_ptr, char *stop);
+
+protected:
+ // Data members:
+ // Methods:
+
+private:
+ // Data members:
+ static const int n_avoids = 42;
+ string avoid[n_avoids] = {"bvup", "epvcmf", "jou", "tusvdu", "dpotu", "gmpbu",
+ "tipsu", "votjhofe", "csfbl", "fmtf", "mpoh", "txjudi",
+ "gvdl", "dpoujovf", "gps", "wbhjob", "tjhofe", "dpdl",
+ "wpje", "dbtf", "tiju", "fovn", "qfojt", "sfhjtufs",
+ "qjtt", "uzqfefg", "efgbvmu", "ujut", "hpup", "tj{fpg",
+ "uxbu", "wpmbujmf", "dvou", "dibs", "fyufso", "sfuvso",
+ "dpjuvt", "vojpo", "ep", "jg", "tubujd", "xijmf"};
+ static const bool capitalize = true;
+ static const bool dont_capitalize = false;
+ // Parameters of random SST-asset generation:
+ // Methods:
+};
+
+#endif /* GIBBERISH_HPP */
diff --git a/tf_fuzz/utility/gibberish.o b/tf_fuzz/utility/gibberish.o
new file mode 100644
index 0000000..b5d4038
--- /dev/null
+++ b/tf_fuzz/utility/gibberish.o
Binary files differ
diff --git a/tf_fuzz/utility/randomization.cpp b/tf_fuzz/utility/randomization.cpp
new file mode 100644
index 0000000..23eb7d2
--- /dev/null
+++ b/tf_fuzz/utility/randomization.cpp
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/**********************************************************************************
+ Functions in this file are exactly that: functions, not methods of any class.
+ That is, they are stand-alone, utility functions linked in to the executable,
+ and available to whomever needs them.
+**********************************************************************************/
+
+#include "randomization.hpp"
+
+/**
+ * \brief Selects and returns a random key_usage_t value.
+ *
+ * \details
+ *
+ * \note
+ *
+ */
+string rand_key_usage (void)
+{
+ switch (rand() % 6) {
+ case 0: return "PSA_KEY_USAGE_EXPORT";
+ case 1: return "PSA_KEY_USAGE_ENCRYPT";
+ case 2: return "PSA_KEY_USAGE_DECRYPT";
+ case 3: return "PSA_KEY_USAGE_SIGN";
+ case 4: return "PSA_KEY_USAGE_VERIFY";
+ case 5: return "PSA_KEY_USAGE_DERIVE";
+ }
+ return ""; /* placate compiler */
+}
+
+/**
+ * \brief Selects and returns a random psa_algorithm_t value.
+ *
+ * \details
+ *
+ * \note
+ *
+ */
+/* TODO: Likely want to make additional versions of these specific for TLS,
+ asymmetric, symmetric... */
+string rand_key_algorithm (void)
+{
+ switch (rand() % 44) {
+ case 0: return "PSA_ALG_VENDOR_FLAG";
+ case 1: return "PSA_ALG_CATEGORY_MASK";
+ case 2: return "PSA_ALG_CATEGORY_HASH";
+ case 3: return "PSA_ALG_CATEGORY_MAC";
+ case 4: return "PSA_ALG_CATEGORY_CIPHER";
+ case 5: return "PSA_ALG_CATEGORY_AEAD";
+ case 6: return "PSA_ALG_CATEGORY_SIGN";
+ case 7: return "PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION";
+ case 8: return "PSA_ALG_CATEGORY_KEY_AGREEMENT";
+ case 9: return "PSA_ALG_CATEGORY_KEY_DERIVATION";
+ case 10: return "PSA_ALG_HASH_MASK";
+ case 11: return "PSA_ALG_MD2";
+ case 12: return "PSA_ALG_MD4";
+ case 13: return "PSA_ALG_MD5";
+ case 14: return "PSA_ALG_RIPEMD160";
+ case 15: return "PSA_ALG_SHA_1";
+ case 16: return "PSA_ALG_SHA_224";
+ case 17: return "PSA_ALG_SHA_256";
+ case 18: return "PSA_ALG_SHA_384";
+ case 19: return "PSA_ALG_SHA_512";
+ case 20: return "PSA_ALG_SHA_512_224";
+ case 21: return "PSA_ALG_SHA_512_256";
+ case 22: return "PSA_ALG_SHA3_224";
+ case 23: return "PSA_ALG_SHA3_256";
+ case 24: return "PSA_ALG_SHA3_384";
+ case 25: return "PSA_ALG_SHA3_512";
+ case 26: return "PSA_ALG_ANY_HASH";
+ case 27: return "PSA_ALG_MAC_SUBCATEGORY_MASK";
+ case 28: return "PSA_ALG_HMAC_BASE";
+ case 29: return "PSA_ALG_MAC_TRUNCATION_MASK";
+ case 30: return "PSA_ALG_CIPHER_MAC_BASE";
+ case 31: return "PSA_ALG_CBC_MAC";
+ case 32: return "PSA_ALG_CMAC";
+ case 33: return "PSA_ALG_CIPHER_STREAM_FLAG";
+ case 34: return "PSA_ALG_CIPHER_FROM_BLOCK_FLAG";
+ case 35: return "PSA_ALG_ARC4";
+ case 36: return "PSA_ALG_CTR";
+ case 37: return "PSA_ALG_CFB";
+ case 38: return "PSA_ALG_OFB";
+ case 39: return "PSA_ALG_XTS";
+ case 40: return "PSA_ALG_CBC_NO_PADDING";
+ case 41: return "PSA_ALG_CBC_PKCS7";
+ case 42: return "PSA_ALG_CCM";
+ case 43: return "PSA_ALG_GCM";
+ }
+ return ""; /* placate compiler */
+}
+
+
+/**
+ * \brief Selects and returns a random psa_key_type_t value.
+ *
+ * \details
+ *
+ * \note
+ *
+ */
+string rand_key_type (void)
+{
+ switch (rand() % 24) {
+ case 0: return "PSA_KEY_TYPE_NONE";
+ case 1: return "PSA_KEY_TYPE_VENDOR_FLAG";
+ case 2: return "PSA_KEY_TYPE_CATEGORY_MASK";
+ case 3: return "PSA_KEY_TYPE_CATEGORY_SYMMETRIC";
+ case 4: return "PSA_KEY_TYPE_CATEGORY_RAW";
+ case 5: return "PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY";
+ case 6: return "PSA_KEY_TYPE_CATEGORY_KEY_PAIR";
+ case 7: return "PSA_KEY_TYPE_CATEGORY_FLAG_PAIR";
+ case 8: return "PSA_KEY_TYPE_RAW_DATA";
+ case 9: return "PSA_KEY_TYPE_HMAC";
+ case 10: return "PSA_KEY_TYPE_DERIVE";
+ case 11: return "PSA_KEY_TYPE_AES";
+ case 12: return "PSA_KEY_TYPE_DES";
+ case 13: return "PSA_KEY_TYPE_CAMELLIA";
+ case 14: return "PSA_KEY_TYPE_ARC4";
+ case 15: return "PSA_KEY_TYPE_CHACHA20";
+ case 16: return "PSA_KEY_TYPE_RSA_PUBLIC_KEY";
+ case 17: return "PSA_KEY_TYPE_RSA_KEY_PAIR";
+ case 18: return "PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE";
+ case 19: return "PSA_KEY_TYPE_ECC_KEY_PAIR_BASE";
+ case 20: return "PSA_KEY_TYPE_ECC_CURVE_MASK";
+ case 21: return "PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE";
+ case 22: return "PSA_KEY_TYPE_DH_KEY_PAIR_BASE";
+ case 23: return "PSA_KEY_TYPE_DH_GROUP_MASK";
+ default: return "";
+ }
+ return ""; /* placate compiler */
+}
+
+
+
diff --git a/tf_fuzz/utility/randomization.hpp b/tf_fuzz/utility/randomization.hpp
new file mode 100644
index 0000000..2eb72f6
--- /dev/null
+++ b/tf_fuzz/utility/randomization.hpp
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef RANDOMIZATION_HPP
+#define RANDOMIZATION_HPP
+
+#include <string>
+
+using namespace std;
+
+string rand_key_usage (void);
+
+string rand_key_algorithm (void);
+
+string rand_key_type (void);
+
+#endif /* #ifndef RANDOMIZATION_HPP */
diff --git a/tf_fuzz/utility/randomization.o b/tf_fuzz/utility/randomization.o
new file mode 100644
index 0000000..1d19db9
--- /dev/null
+++ b/tf_fuzz/utility/randomization.o
Binary files differ
diff --git a/tf_fuzz/utility/string_ops.cpp b/tf_fuzz/utility/string_ops.cpp
new file mode 100644
index 0000000..9c14140
--- /dev/null
+++ b/tf_fuzz/utility/string_ops.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "string_ops.hpp"
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+
+using namespace std;
+
+// Replace first occurrence of find_str within orig of replace_str:
+size_t find_replace_1st (const string &find_str, const string &replace_str,
+ string &orig) {
+ size_t where = 0;
+ where = orig.find(find_str, where);
+ if (where != string::npos) {
+ orig.replace(where, find_str.length(), replace_str);
+ }
+ return where;
+}
+
+// Replace all occurrences of find_str in "this" string, with replace_str:
+size_t find_replace_all (const string &find_str, const string &replace_str,
+ string &orig) {
+ size_t where = 0;
+ do {
+ where = orig.find(find_str, where);
+ if (where != string::npos) {
+ orig.replace(where, find_str.length(), replace_str);
+ }
+ } while (where != string::npos);
+ return where;
+}
+
+
+string formalize (string input, string prefix) {
+ // First capitalize the input string:
+ for (auto cp = input.begin(); cp < input.end(); cp++) {
+ *cp = (char) toupper (*cp);
+ }
+ // If it already begins with the prefix...
+ if (input.substr (0, prefix.length()) == prefix) {
+ // then return it as capitalized:
+ return input;
+ } else {
+ // If not, prefix it with that prefix:
+ return prefix + input;
+ }
+}
+
+/* This implementation assumes ASCII character encoding and no "special characters" --
+ loosely speaking, "English." */
+string string_or_hex (string input, int clump_size) {
+ uint32_t n_alphanum = 0; // the number of alphanumeric characters
+ bool prose = true; // the string is alphanumeric, space, or common punctuation
+ ostringstream hex_stream;
+
+ for (auto cp = input.begin(); cp < input.end(); cp++) {
+ if ((int) *cp < 0) {
+ prose = false;
+ break;
+ }
+ if ( (*cp >= '0' && *cp <= '9')
+ || (*cp >= 'a' && *cp <= 'z') || (*cp >= 'A' && *cp <= 'Z')
+ || (*cp == ' ') || (*cp == ',') || (*cp == '.')
+ || (*cp == '?') || (*cp == '!')
+ ) {
+ n_alphanum++;
+ }
+ }
+ if ( prose // so far at least!
+ && ( (input.length() - n_alphanum) // number of chars that are not "English"
+ < (input.length() >> 3) // 1/8 of the length of the string
+ ) ) {
+ return input; // take it at face-value
+ }
+ // It's not run-of-the-mill text, so create a hex string:
+ int i = 0;
+ for (auto cp = input.begin(); cp < input.end(); cp++) {
+ hex_stream << setfill('0') << setw(2) << hex << (((unsigned) *cp) & 0xff);
+ if (++i >= clump_size) {
+ hex_stream << " ";
+ i = 0;
+ }
+ }
+ return hex_stream.str();
+}
+
+string binary_from_hex (string input) {
+ stringstream hex_stream;
+ uint8_t aByte; // each byte as we grab it
+ string result = "";
+ string holder_string = "";
+
+ hex_stream.str(input);
+ hex_stream.width(2);
+ while (!hex_stream.eof()) {
+ hex_stream >> skipws >> setw(2) >> holder_string;
+ try { // TODO: May not catch all bad-chars.
+ aByte = stoi(holder_string, 0, 16);
+ }
+ catch (const invalid_argument &arg_err) {
+ cerr << "Error 2345: Non-hexadecimal character found in binary-data string ("
+ << arg_err.what() << endl;
+ exit (2345);
+ }
+ result += aByte;
+ }
+ return result;
+}
diff --git a/tf_fuzz/utility/string_ops.hpp b/tf_fuzz/utility/string_ops.hpp
new file mode 100644
index 0000000..83e4d9a
--- /dev/null
+++ b/tf_fuzz/utility/string_ops.hpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef STRING_OPS_HPP
+#define STRING_OPS_HPP
+
+#include <cstddef>
+#include <string>
+
+using namespace std;
+
+// Replace first occurrence of find_str within orig of replace_str:
+size_t find_replace_1st (const string &find_str, const string &replace_str,
+ string &orig);
+
+// Replace all occurrences of find_str in "this" string, with replace_str:
+size_t find_replace_all (const string &find_str, const string &replace_str,
+ string &orig);
+
+/* In both of the above string-replacement functions, the return value is start
+ offset to the (last) occurrence of "find_str" within "orig." */
+
+/* formalize() turns an abbreviated, "human" name for a PSA setting into its
+ presumed official name. Examples:
+ "export" with prefix "PSA_KEY_USAGE_" becomes "PSA_KEY_USAGE_EXPORT".
+ "generic_error" with prefix "PSA_ERROR_" becomes "PSA_ERROR_GENERIC_ERROR".
+ "PSA_ERROR_INVALID_ARGUMENT" stays unchanged as "PSA_ERROR_INVALID_ARGUMENT".
+*/
+string formalize (string input, string prefix);
+
+/* string_or_hex() takes a string (e.g., describing a key's "material" -- data),
+ and:
+ * If it "appears to be" alphanumeric, then returns it unaltered.
+ * Otherwise, if it "appears to be binary data, it returns a new string of
+ it as hex digits.
+ * clump_size is how many bytes to clump together between spaces */
+string string_or_hex (string input, int clump_size);
+
+/* binary_from_hex() takes a string of hex characters, and returns a string
+ containing those raw byte values (i.e., not human-readable, and not really
+ a string in the usual sense of the word). In the future, it would be good
+ to address binary data better. */
+string binary_from_hex (string input);
+
+#endif // #ifndef STRING_OPS_HPP
diff --git a/tf_fuzz/utility/string_ops.o b/tf_fuzz/utility/string_ops.o
new file mode 100644
index 0000000..5f3d9ac
--- /dev/null
+++ b/tf_fuzz/utility/string_ops.o
Binary files differ
diff --git a/tf_fuzz/utility/variables.cpp b/tf_fuzz/utility/variables.cpp
new file mode 100644
index 0000000..ab2a823
--- /dev/null
+++ b/tf_fuzz/utility/variables.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/* This file defines information to track regarding variables in the generated test
+ code. */
+
+#include <string>
+#include <vector>
+#include <list>
+#include <iostream>
+#include <fstream>
+
+#include "class_forwards.hpp"
+
+#include "data_blocks.hpp"
+#include "psa_asset.hpp"
+#include "crypto_asset.hpp"
+#include "psa_call.hpp"
+#include "find_or_create_asset.hpp"
+#include "variables.hpp"
+#include "gibberish.hpp"
+
+/* 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. However these in particular are mostly axiomatic: Not
+ dependent upon other classes. */
+
+
+using namespace std;
+
+
+/**********************************************************************************
+ Methods of class variable_info follow:
+**********************************************************************************/
+
+variable_info::variable_info (void) // (default constructor)
+{
+ gibberish *gib = new gibberish;
+
+ hash_declared = value_known = false;
+ name = "";
+ length = 100 + (rand() % 800);
+ gib->sentence ((char*) value, (char*) value + length);
+ // TODO: Sizes of random data neesds to be strategized better
+ type = psa_asset_type::unknown;
+ delete gib;
+}
+
+variable_info::variable_info (string var_name, psa_asset_type var_type)
+{ // (constructor with known name and type)
+ gibberish *gib = new gibberish;
+
+ hash_declared = value_known = false;
+ name.assign (var_name);
+ length = 100 + (rand() % 800);
+ gib->sentence ((char*) value, (char*) value + length);
+ // TODO: Sizes of random data needs to be strategized better
+ type = var_type;
+ delete gib;
+}
+
+variable_info::~variable_info (void) // (destructor)
+{}
+
+
+/**********************************************************************************
+ End of methods of class variable_info.
+**********************************************************************************/
diff --git a/tf_fuzz/utility/variables.hpp b/tf_fuzz/utility/variables.hpp
new file mode 100644
index 0000000..886acc3
--- /dev/null
+++ b/tf_fuzz/utility/variables.hpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <string>
+#include <vector>
+
+/* This file defines information to track regarding variables in the generated test
+ code. */
+
+#ifndef VARIABLES_HPP
+#define VARIABLES_HPP
+
+/* 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. However these in particular are mostly axiomatic: Not
+ dependent upon other classes. */
+
+
+using namespace std;
+
+
+/**********************************************************************************
+ Class variable_info tracks everything we know about a given variable in the
+ generated C code.
+**********************************************************************************/
+
+class variable_info
+{
+public:
+ // Data members:
+ /* The existence of this variable tracker means that the data variable and
+ the length variable have been declared, but there are other variants on
+ this variable that may or may not have been declared already. Thus
+ the *_declared bool(s) below. */
+ bool hash_declared; // true if the hash of this variable has been declared
+ bool value_known; // true if the variable's value can be known in simulation
+ string name; // variable name
+ unsigned char value[2048]; // the current value of the variable
+ int length; // of the variable's value
+ psa_asset_type type; // type of info contained in the variable
+
+ // Methods:
+ variable_info (void); // (default constructor)
+ variable_info ( // (constructor with known name and type)
+ string var_name, psa_asset_type var_type
+ );
+ ~variable_info (void); // (destructor)
+
+protected:
+ // Data members:
+};
+
+
+#endif // VARIABLES_HPP
+
diff --git a/tf_fuzz/utility/variables.o b/tf_fuzz/utility/variables.o
new file mode 100644
index 0000000..bc7772a
--- /dev/null
+++ b/tf_fuzz/utility/variables.o
Binary files differ