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/utility/README b/tools/tf_fuzz/utility/README
new file mode 100644
index 0000000..012fefd
--- /dev/null
+++ b/tools/tf_fuzz/utility/README
@@ -0,0 +1,15 @@
+.../tf_fuzz/utility directory contents:
+
+compute.cpp      find_or_create_asset.hpp  randomization.cpp  string_ops.hpp
+compute.hpp      gibberish.cpp             randomization.hpp
+data_blocks.cpp  gibberish.hpp             Source.cpp
+data_blocks.hpp  interactive.c             string_ops.cpp
+
+--------------------------------------------------------------------------------
+
+As its name implies, this .../utility directory just contains various utility-
+compute "stuff."
+
+--------------
+
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
diff --git a/tools/tf_fuzz/utility/compute.cpp b/tools/tf_fuzz/utility/compute.cpp
new file mode 100644
index 0000000..708a1f3
--- /dev/null
+++ b/tools/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/tools/tf_fuzz/utility/compute.hpp b/tools/tf_fuzz/utility/compute.hpp
new file mode 100644
index 0000000..c6ece6c
--- /dev/null
+++ b/tools/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/tools/tf_fuzz/utility/data_blocks.cpp b/tools/tf_fuzz/utility/data_blocks.cpp
new file mode 100644
index 0000000..172d672
--- /dev/null
+++ b/tools/tf_fuzz/utility/data_blocks.cpp
@@ -0,0 +1,242 @@
+/*
+ * 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 "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_specified = false;
+    pf_result_string.assign ("");  data.assign ("");
+    data_var_specified = false;
+    data_var.assign ("");  // name of expected-data variable
+    data_specified = false;
+    data.assign ("");
+    pf_info_incomplete = true;
+}
+expect_info::~expect_info (void)  // (destructor)
+{}
+
+void expect_info::set_pf_pass (void)
+{
+    pf_pass = true;
+    pf_nothing = pf_specified = false;
+    pf_result_string = "";
+}
+
+void expect_info::set_pf_nothing (void)
+{
+    pf_nothing = true;
+    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_nothing = false;
+}
+
+/* What the call expects is 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->expect.pf_nothing = pf_nothing;
+    the_call->expect.pf_pass = pf_pass;
+    the_call->expect.pf_specified = pf_specified;
+    the_call->expect.pf_result_string = pf_result_string;
+    the_call->expect.pf_info_incomplete = false;
+}
+
+/**********************************************************************************
+   End of methods of class expect_info.
+**********************************************************************************/
+
+
+/**********************************************************************************
+   Class set_data_info methods regarding setting and getting asset-data values:
+**********************************************************************************/
+
+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 ("");
+}
+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);
+}
+
+/* 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 = 100 + (rand() % 10000);  // default to random ID# (e.g., SST UID)
+    asset_name.assign ("");
+    id_n_specified = name_specified = false;  // no ID info yet
+    asset_name_vector.clear();
+    asset_id_n_vector.clear();
+}
+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 = 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 = 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 = 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 &name)
+{
+    string result = "SST_ID_";
+    result.append(to_string(id_n));
+    return result;
+}
+
+/**********************************************************************************
+   End of methods of class asset_name_id_info.
+**********************************************************************************/
diff --git a/tools/tf_fuzz/utility/data_blocks.hpp b/tools/tf_fuzz/utility/data_blocks.hpp
new file mode 100644
index 0000000..2822f57
--- /dev/null
+++ b/tools/tf_fuzz/utility/data_blocks.hpp
@@ -0,0 +1,144 @@
+/*
+ * 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:
+        bool pf_nothing;  // true to not generate results-check(s)
+        bool pf_pass;  // if !expect.pf_nothing, then pass is expected
+        bool pf_specified;
+            /* if !pf_nothing && !pf_pass, then
+               true == expected result was specified
+               false == tf_fuzz must model expected result */
+        bool data_specified;  // (literal data specified)
+        string data;  // expected data from reading an asset
+        bool data_var_specified;
+        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 expect
+               info when it comes available. */
+        // Expected-result info:
+        string pf_result_string;
+            // if !pf_nothing && !pf_pass then this is expected result
+    // Methods:
+        expect_info (void);  // (default constructor)
+        ~expect_info (void);  // (destructor)
+        void set_pf_pass (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 expected 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
+        string file_path;  // path to file, if specified
+    // Methods:
+        set_data_info (void);  // (default constructor)
+        ~set_data_info (void);  // (destructor)
+        void set (string set_val);
+        void set_calculated (string set_val);
+        string get (void);
+        bool set_file (string file_name);
+
+protected:
+    // Data members:
+        string data;  // String describing asset data.
+};
+
+
+/**********************************************************************************
+  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)
+        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;
+        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_id.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, string &name);
+            // create UID-based asset name
+
+protected:
+    // Data members:
+        string asset_name;  // parsed from template, assigned to psa_asset object
+};
+
+
+
+#endif // DATA_BLOCKS_HPP
+
diff --git a/tools/tf_fuzz/utility/find_or_create_asset.hpp b/tools/tf_fuzz/utility/find_or_create_asset.hpp
new file mode 100644
index 0000000..866c949
--- /dev/null
+++ b/tools/tf_fuzz/utility/find_or_create_asset.hpp
@@ -0,0 +1,156 @@
+/*
+ * 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
+
+/* 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 one
+    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,  // found as a previously-used, but now-unusable asset
+    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
+};
+
+
+// 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_id.get_name() == target_name);
+                    break;
+                case psa_asset_search::id:  // ID#
+                    match = (pass->asset_id.id_n == target_id);
+                    break;
+                default:  // psa_asset_search::serial
+                    match = (pass->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_id.get_name() == target_name);
+                    break;
+                case psa_asset_search::id:  // ID#
+                    match = (pass->asset_id.id_n == target_id);
+                    break;
+                default:  // psa_asset_search::serial
+                    match = (pass->asset_ser_no == serial_no);
+                    break;
+            }
+            if (match) {
+                asset = as;
+                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_id.get_name() == target_name);
+                    break;
+                case psa_asset_search::id:  // ID#
+                    match = (pass->asset_id.id_n == target_id);
+                    break;
+                default:  // psa_asset_search::serial
+                    match = (pass->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_id.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/tools/tf_fuzz/utility/gibberish.cpp b/tools/tf_fuzz/utility/gibberish.cpp
new file mode 100644
index 0000000..45ce223
--- /dev/null
+++ b/tools/tf_fuzz/utility/gibberish.cpp
@@ -0,0 +1,191 @@
+/*
+ * 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 */
+
+    for (syllable_count = 0, parser = string_ptr;
+            syllable_count < 4
+         && (rand() % 4) >= syllable_count
+         && parser < stop;
+         syllable_count++) {
+        parser = syllable (parser, stop);
+    }
+    if (initial_cap) {
+        *string_ptr -= 'a' - 'A';  /* more or less assumes ASCII */
+    }
+    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)
+{
+    // Nothing to set up.
+}
+
+
+/**
+ * \brief Destructor for gibberish object.
+ *
+ */
+gibberish::~gibberish (void)
+{
+    // Nothing to tear down.
+}
diff --git a/tools/tf_fuzz/utility/gibberish.hpp b/tools/tf_fuzz/utility/gibberish.hpp
new file mode 100644
index 0000000..5efd419
--- /dev/null
+++ b/tools/tf_fuzz/utility/gibberish.hpp
@@ -0,0 +1,50 @@
+/*
+ * 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 bool capitalize = true;
+    static const bool dont_capitalize = false;
+    // Parameters of random SST-asset generation:
+    // Methods:
+};
+
+#endif /* GIBBERISH_HPP */
diff --git a/tools/tf_fuzz/utility/randomization.cpp b/tools/tf_fuzz/utility/randomization.cpp
new file mode 100644
index 0000000..8abfe5c
--- /dev/null
+++ b/tools/tf_fuzz/utility/randomization.cpp
@@ -0,0 +1,139 @@
+/*
+ * 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() % 47) {
+        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_CATEGORY_KEY_SELECTION";
+        case 11:  return "PSA_ALG_KEY_SELECTION_FLAG";
+        case 12:  return "PSA_ALG_HASH_MASK";
+        case 13:  return "PSA_ALG_MD2";
+        case 14:  return "PSA_ALG_MD4";
+        case 15:  return "PSA_ALG_MD5";
+        case 16:  return "PSA_ALG_RIPEMD160";
+        case 17:  return "PSA_ALG_SHA_1";
+        case 18:  return "PSA_ALG_SHA_224";
+        case 19:  return "PSA_ALG_SHA_256";
+        case 20:  return "PSA_ALG_SHA_384";
+        case 21:  return "PSA_ALG_SHA_512";
+        case 22:  return "PSA_ALG_SHA_512_224";
+        case 23:  return "PSA_ALG_SHA_512_256";
+        case 24:  return "PSA_ALG_SHA3_224";
+        case 25:  return "PSA_ALG_SHA3_256";
+        case 26:  return "PSA_ALG_SHA3_384";
+        case 27:  return "PSA_ALG_SHA3_512";
+        case 28:  return "PSA_ALG_ANY_HASH";
+        case 29:  return "PSA_ALG_MAC_SUBCATEGORY_MASK";
+        case 30:  return "PSA_ALG_HMAC_BASE";
+        case 31:  return "PSA_ALG_MAC_TRUNCATION_MASK";
+        case 32:  return "PSA_ALG_CIPHER_MAC_BASE";
+        case 33:  return "PSA_ALG_CBC_MAC";
+        case 34:  return "PSA_ALG_CMAC";
+        case 35:  return "PSA_ALG_GMAC";
+        case 36:  return "PSA_ALG_CIPHER_STREAM_FLAG";
+        case 37:  return "PSA_ALG_CIPHER_FROM_BLOCK_FLAG";
+        case 38:  return "PSA_ALG_ARC4";
+        case 39:  return "PSA_ALG_CTR";
+        case 40:  return "PSA_ALG_CFB";
+        case 41:  return "PSA_ALG_OFB";
+        case 42:  return "PSA_ALG_XTS";
+        case 43:  return "PSA_ALG_CBC_NO_PADDING";
+        case 44:  return "PSA_ALG_CBC_PKCS7";
+        case 45:  return "PSA_ALG_CCM";
+        case 46:  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() % 22) {
+        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_RSA_PUBLIC_KEY";
+        case 16:  return "PSA_KEY_TYPE_RSA_KEYPAIR";
+        case 17:  return "PSA_KEY_TYPE_DSA_PUBLIC_KEY";
+        case 18:  return "PSA_KEY_TYPE_DSA_KEYPAIR";
+        case 19:  return "PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE";
+        case 20:  return "PSA_KEY_TYPE_ECC_KEYPAIR_BASE";
+        case 21:  return "PSA_KEY_TYPE_ECC_CURVE_MASK";
+        default:  return "";
+    }
+    return "";  /* placate compiler */
+}
+
diff --git a/tools/tf_fuzz/utility/randomization.hpp b/tools/tf_fuzz/utility/randomization.hpp
new file mode 100644
index 0000000..2eb72f6
--- /dev/null
+++ b/tools/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/tools/tf_fuzz/utility/string_ops.cpp b/tools/tf_fuzz/utility/string_ops.cpp
new file mode 100644
index 0000000..a25a777
--- /dev/null
+++ b/tools/tf_fuzz/utility/string_ops.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "string_ops.hpp"
+
+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;
+}
diff --git a/tools/tf_fuzz/utility/string_ops.hpp b/tools/tf_fuzz/utility/string_ops.hpp
new file mode 100644
index 0000000..697a342
--- /dev/null
+++ b/tools/tf_fuzz/utility/string_ops.hpp
@@ -0,0 +1,27 @@
+/*
+ * 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." */
+
+#endif  // #ifndef STRING_OPS_HPP