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/Makefile b/tools/tf_fuzz/Makefile
new file mode 100644
index 0000000..6d8be2b
--- /dev/null
+++ b/tools/tf_fuzz/Makefile
@@ -0,0 +1,225 @@
+# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+.PHONY: default
+default: tfz;
+
+edit:
+	$(EDITOR) template/template_line.hpp \
+	template/sst_template_line.hpp template/crypto_template_line.hpp \
+	template/secure_template_line.hpp calls/psa_call.hpp calls/sst_call.hpp \
+	calls/crypto_call.hpp calls/security_call.hpp assets/psa_asset.hpp \
+	assets/sst_asset.hpp assets/crypto_asset.hpp  utility/data_blocks.hpp \
+	utility/gibberish.hpp utility/randomization.hpp \
+	utility/find_or_create_asset.hpp utility/string_ops.hpp \
+	utility/compute.hpp boilerplate/boilerplate.hpp \
+	utility/find_or_create_asset.hpp class_forwards.hpp tf_fuzz.hpp \
+	parser/tf_fuzz_grammar.l parser/tf_fuzz_grammar.y \
+	template/template_line.cpp \
+	template/sst_template_line.cpp template/crypto_template_line.cpp \
+	template/secure_template_line.cpp calls/psa_call.cpp calls/sst_call.cpp \
+	calls/crypto_call.cpp calls/security_call.cpp assets/psa_asset.cpp \
+	assets/sst_asset.cpp assets/crypto_asset.cpp utility/data_blocks.cpp \
+	utility/gibberish.cpp utility/randomization.cpp utility/string_ops.cpp \
+	utility/compute.cpp \
+	boilerplate/boilerplate.cpp tf_fuzz.cpp \
+	tests/example_template tests/sstSets tests/sstReads \
+	lib/tfm_boilerplate.txt boilerplate/boilerplate.hpp \
+	Makefile README assets/README \
+	boilerplate/README calls/README demo/README lib/README parser/README \
+	template/README tests/README regression/README utility/README \
+	visualStudio/README &
+
+edit3:
+	$(EDITOR) template/template_line.hpp \
+	template/sst_template_line.hpp template/crypto_template_line.hpp \
+	template/secure_template_line.hpp calls/psa_call.hpp calls/sst_call.hpp \
+	calls/crypto_call.hpp calls/security_call.hpp assets/psa_asset.hpp \
+	assets/sst_asset.hpp assets/crypto_asset.hpp  utility/data_blocks.hpp \
+	utility/gibberish.hpp utility/randomization.hpp \
+	utility/find_or_create_asset.hpp utility/string_ops.hpp \
+	utility/compute.hpp boilerplate/boilerplate.hpp \
+	utility/find_or_create_asset.hpp class_forwards.hpp tf_fuzz.hpp &
+	$(EDITOR) parser/tf_fuzz_grammar.l parser/tf_fuzz_grammar.y \
+	template/template_line.cpp \
+	template/sst_template_line.cpp template/crypto_template_line.cpp \
+	template/secure_template_line.cpp calls/psa_call.cpp calls/sst_call.cpp \
+	calls/crypto_call.cpp calls/security_call.cpp assets/psa_asset.cpp \
+	assets/sst_asset.cpp assets/crypto_asset.cpp utility/data_blocks.cpp \
+	utility/gibberish.cpp utility/randomization.cpp utility/string_ops.cpp \
+	utility/compute.cpp \
+	boilerplate/boilerplate.cpp tf_fuzz.cpp &
+	$(EDITOR) tests/example_template tests/sstSets tests/sstReads \
+	lib/tfm_boilerplate.txt boilerplate/boilerplate.hpp \
+	Makefile README assets/README \
+	boilerplate/README calls/README demo/README lib/README parser/README \
+	template/README tests/README regression/README utility/README \
+	visualStudio/README &
+
+includes = -I . -I ./parser -I ./template -I ./assets -I ./calls -I ./boilerplate -I ./utility
+
+parser/tf_fuzz_grammar.tab.hpp:  parser/tf_fuzz_grammar.y class_forwards.hpp \
+boilerplate/boilerplate.hpp utility/gibberish.hpp utility/string_ops.hpp \
+tf_fuzz.hpp utility/data_blocks.hpp utility/find_or_create_asset.hpp assets/psa_asset.hpp \
+assets/sst_asset.hpp assets/crypto_asset.hpp calls/psa_call.hpp \
+template/template_line.hpp Makefile
+	rm -f parser/tf_fuzz_grammar.tab.hpp parser/tf_fuzz_grammar.tab.cpp \
+	parser/tf_fuzz_grammar.tab.o
+	bison --verbose -d parser/tf_fuzz_grammar.y -o \
+	parser/tf_fuzz_grammar.tab.cpp
+
+parser/tf_fuzz_grammar.tab.cpp:  parser/tf_fuzz_grammar.y class_forwards.hpp \
+boilerplate/boilerplate.hpp utility/gibberish.hpp utility/string_ops.hpp \
+tf_fuzz.hpp utility/data_blocks.hpp utility/find_or_create_asset.hpp assets/psa_asset.hpp \
+assets/sst_asset.hpp assets/crypto_asset.hpp calls/psa_call.hpp \
+template/template_line.hpp Makefile
+	rm -f parser/tf_fuzz_grammar.tab.hpp parser/tf_fuzz_grammar.tab.cpp \
+	parser/tf_fuzz_grammar.tab.o
+	bison --verbose -d parser/tf_fuzz_grammar.y -o \
+	parser/tf_fuzz_grammar.tab.cpp
+
+parser/tf_fuzz_grammar.lex.c:  parser/tf_fuzz_grammar.l \
+parser/tf_fuzz_grammar.tab.hpp Makefile
+	lex --outfile=parser/tf_fuzz_grammar.lex.c parser/tf_fuzz_grammar.l
+parser/tf_fuzz_grammar.lex.o:  parser/tf_fuzz_grammar.lex.c Makefile
+	g++ -std=gnu++11 -O0 -g -c -I /usr/include $(includes) -o parser/tf_fuzz_grammar.lex.o \
+	parser/tf_fuzz_grammar.lex.c
+
+parser/tf_fuzz_grammar.tab.o:  parser/tf_fuzz_grammar.lex.o \
+parser/tf_fuzz_grammar.tab.cpp parser/tf_fuzz_grammar.tab.hpp Makefile
+	g++ -Wall -std=c++11 -O0 -g -c -I /usr/include $(includes) -o \
+	parser/tf_fuzz_grammar.tab.o parser/tf_fuzz_grammar.tab.cpp
+
+utility/data_block.o:  utility/data_blocks.hpp utility/data_blocks.cpp  Makefile
+	g++ -Wall -std=c++11 -O0 -g -c $(includes) -o utility/data_block.o \
+	utility/data_blocks.cpp
+
+template/template_line.o:  utility/randomization.hpp template/template_line.cpp \
+class_forwards.hpp boilerplate/boilerplate.hpp tf_fuzz.hpp calls/psa_call.hpp \
+assets/psa_asset.hpp utility/data_blocks.hpp template/template_line.hpp assets/sst_asset.hpp \
+assets/crypto_asset.hpp  Makefile
+	g++ -Wall -std=c++11 -O0 -g -c $(includes) -o template/template_line.o \
+	template/template_line.cpp
+
+template/sst_template_line.o:  template/sst_template_line.cpp class_forwards.hpp \
+boilerplate/boilerplate.hpp tf_fuzz.hpp calls/psa_call.hpp assets/psa_asset.hpp \
+utility/data_blocks.hpp template/template_line.hpp template/sst_template_line.hpp assets/sst_asset.hpp \
+assets/crypto_asset.hpp Makefile
+	g++ -Wall -std=c++11 -O0 -g -c $(includes) -o template/sst_template_line.o \
+	template/sst_template_line.cpp
+
+template/crypto_template_line.o:  template/crypto_template_line.cpp \
+class_forwards.hpp boilerplate/boilerplate.hpp tf_fuzz.hpp calls/psa_call.hpp \
+assets/psa_asset.hpp utility/data_blocks.hpp template/template_line.hpp assets/sst_asset.hpp \
+assets/crypto_asset.hpp template/crypto_template_line.hpp Makefile
+	g++ -Wall -std=c++11 -O0 -g -c $(includes) -o template/crypto_template_line.o \
+	template/crypto_template_line.cpp
+
+template/secure_template_line.o:  utility/randomization.hpp class_forwards.hpp \
+boilerplate/boilerplate.hpp tf_fuzz.hpp calls/psa_call.hpp \
+assets/psa_asset.hpp utility/data_blocks.hpp template/secure_template_line.hpp assets/sst_asset.hpp \
+assets/crypto_asset.hpp  Makefile
+	g++ -Wall -std=c++11 -O0 -g -c $(includes) -o template/secure_template_line.o \
+	template/secure_template_line.cpp
+
+assets/psa_asset.o:  assets/psa_asset.cpp class_forwards.hpp \
+boilerplate/boilerplate.hpp tf_fuzz.hpp utility/data_blocks.hpp calls/psa_call.hpp assets/psa_asset.hpp \
+template/template_line.hpp Makefile
+	g++ -Wall -std=c++11 -O0 -g -c $(includes) -o assets/psa_asset.o \
+	assets/psa_asset.cpp
+
+assets/sst_asset.o:  assets/sst_asset.cpp class_forwards.hpp \
+boilerplate/boilerplate.hpp utility/data_blocks.hpp tf_fuzz.hpp calls/psa_call.hpp assets/psa_asset.hpp \
+template/template_line.hpp assets/sst_asset.hpp  Makefile
+	g++ -Wall -std=c++11 -O0 -g -c $(includes) -o assets/sst_asset.o \
+	assets/sst_asset.cpp
+
+assets/crypto_asset.o:  utility/randomization.hpp assets/crypto_asset.cpp \
+class_forwards.hpp boilerplate/boilerplate.hpp tf_fuzz.hpp utility/data_blocks.hpp calls/psa_call.hpp \
+assets/psa_asset.hpp assets/crypto_asset.hpp Makefile
+	g++ -Wall -std=c++11 -O0 -g -c $(includes) -o assets/crypto_asset.o \
+	assets/crypto_asset.cpp
+
+calls/psa_call.o:  calls/psa_call.cpp class_forwards.hpp \
+boilerplate/boilerplate.hpp utility/data_blocks.hpp tf_fuzz.hpp calls/psa_call.hpp Makefile
+	g++ -Wall -std=c++11 -O0 -g -c $(includes) -o calls/psa_call.o calls/psa_call.cpp
+
+calls/sst_call.o:  calls/sst_call.cpp class_forwards.hpp \
+boilerplate/boilerplate.hpp tf_fuzz.hpp calls/psa_call.hpp assets/psa_asset.hpp \
+template/template_line.hpp utility/data_blocks.hpp calls/sst_call.hpp assets/sst_asset.hpp \
+assets/crypto_asset.hpp utility/string_ops.hpp Makefile
+	g++ -Wall -std=c++11 -O0 -g -c $(includes) -o calls/sst_call.o \
+	calls/sst_call.cpp
+
+calls/crypto_call.o:  utility/randomization.hpp calls/crypto_call.cpp \
+class_forwards.hpp boilerplate/boilerplate.hpp utility/string_ops.hpp \
+tf_fuzz.hpp calls/psa_call.hpp utility/data_blocks.hpp assets/psa_asset.hpp template/template_line.hpp \
+calls/crypto_call.hpp assets/sst_asset.hpp assets/crypto_asset.hpp Makefile
+	g++ -Wall -std=c++11 -O0 -g -c $(includes) -o calls/crypto_call.o \
+	calls/crypto_call.cpp
+
+calls/security_call.o:  utility/randomization.hpp calls/security_call.hpp \
+calls/security_call.cpp class_forwards.hpp boilerplate/boilerplate.hpp \
+utility/string_ops.hpp utility/data_blocks.hpp tf_fuzz.hpp calls/psa_call.hpp assets/psa_asset.hpp \
+template/template_line.hpp calls/security_call.hpp assets/sst_asset.hpp \
+Makefile
+	g++ -Wall -std=c++11 -O0 -g -c $(includes) -o calls/security_call.o \
+	calls/security_call.cpp
+
+boilerplate/boilerplate.o:  boilerplate/boilerplate.cpp class_forwards.hpp \
+boilerplate/boilerplate.hpp tf_fuzz.hpp calls/psa_call.hpp assets/psa_asset.hpp \
+template/template_line.hpp Makefile
+	g++ -Wall -std=c++11 -O0 -g -c $(includes) -o boilerplate/boilerplate.o \
+	boilerplate/boilerplate.cpp
+
+utility/gibberish.o:  utility/gibberish.cpp class_forwards.hpp \
+utility/gibberish.hpp Makefile
+	g++ -Wall -std=c++11 -O0 -g -c $(includes) -o utility/gibberish.o \
+	utility/gibberish.cpp
+
+utility/string_ops.o:  utility/string_ops.cpp utility/string_ops.hpp Makefile
+	g++ -Wall -std=c++11 -O0 -g -c $(includes) -o utility/string_ops.o \
+	utility/string_ops.cpp
+
+utility/randomization.o:  utility/randomization.cpp utility/randomization.hpp \
+Makefile
+	g++ -Wall -std=c++11 -O0 -g -c $(includes) -o utility/randomization.o \
+	utility/randomization.cpp
+
+utility/compute.o:  utility/compute.cpp utility/compute.hpp Makefile
+	g++ -Wall -std=c++11 -O0 -g -c $(includes) -o utility/compute.o \
+	utility/compute.cpp
+
+tf_fuzz.o:  tf_fuzz.cpp class_forwards.hpp boilerplate/boilerplate.hpp tf_fuzz.hpp \
+calls/psa_call.hpp assets/psa_asset.hpp utility/data_blocks.hpp template/template_line.hpp \
+parser/tf_fuzz_grammar.tab.hpp Makefile
+	g++ -Wall -std=c++11 -O0 -g -c $(includes) -o tf_fuzz.o tf_fuzz.cpp
+
+tfz:  parser/tf_fuzz_grammar.lex.o parser/tf_fuzz_grammar.tab.o \
+template/secure_template_line.o template/template_line.o \
+template/sst_template_line.o template/crypto_template_line.o utility/data_block.o \
+assets/psa_asset.o assets/sst_asset.o assets/crypto_asset.o utility/gibberish.o \
+utility/string_ops.o calls/psa_call.o calls/sst_call.o calls/crypto_call.o \
+utility/randomization.o utility/compute.o boilerplate/boilerplate.o \
+calls/security_call.o tf_fuzz.o \
+Makefile
+	g++ -Wall -std=c++11 -O0 -g -o tfz parser/tf_fuzz_grammar.lex.o \
+	parser/tf_fuzz_grammar.tab.o template/secure_template_line.o \
+	template/template_line.o template/sst_template_line.o utility/data_block.o \
+	template/crypto_template_line.o assets/psa_asset.o assets/sst_asset.o \
+	assets/crypto_asset.o utility/gibberish.o utility/string_ops.o \
+	utility/randomization.o utility/compute.o calls/psa_call.o \
+	calls/sst_call.o calls/crypto_call.o calls/security_call.o \
+	boilerplate/boilerplate.o tf_fuzz.o
+
+clean:
+	rm -f ./*.o parser/*.o assets/*.o calls/*.o template/*.o utility/*.o \
+	boilerplate/*.o utility/gibberish.o tfz tfz.exe \
+	parser/tf_fuzz_grammar.lex.* parser/tf_fuzz_grammar.tab.* \
+	parser/tf_fuzz_grammar.output
+	rm -f `find regression -name "stdout_stderr"`
+	rm -f `find regression -name "test.c"`
+	rm -f `find regression -name "diff_*"`
+	rm -f demo/tossThis*
diff --git a/tools/tf_fuzz/README b/tools/tf_fuzz/README
new file mode 100644
index 0000000..47e2663
--- /dev/null
+++ b/tools/tf_fuzz/README
@@ -0,0 +1,125 @@
+.../tf_fuzz directory contents:
+
+assets       calls               demo      parser    tests        regression
+backupStuff  class_forwards.hpp  lib       README    tf_fuzz.cpp  utility
+boilerplate  commands            Makefile  template  tf_fuzz.hpp  visualStudio
+
+TF-Fuzz root directory.
+
+--------------------------------------------------------------------------------
+
+TF-Fuzz is a TF-M fuzzing tool, at the PSA-call level.  At the time of writing
+this at least, presentations available at:
+    https://www.trustedfirmware.org/docs/TF-M_Fuzzing_Tool_TFOrg.pdf
+    https://zoom.us/rec/share/1dxZcZit111IadadyFqFU7IoP5X5aaa8gXUdr_UInxmMbyLzEqEmXQdx79-IWQ9p
+(These presentation materials may not be viewable by all parties.)
+
+--------------------------------------------------------------------------------
+
+To build TF-Fuzz, simply type "make" in this directory.  Executable, called
+"tfz," is placed in this directory.
+
+To run tfz, two environment variables must first be assigned.  In bash syntax:
+export TF_FUZZ_LIB_DIR=<path to this TF-M installation>/tools/tf_fuzz/lib
+export TF_FUZZ_BPLATE=tfm_boilerplate.txt
+
+Examples of usage can be found in the demo directory.
+
+--------------------------------------------------------------------------------
+
+To help understand the code, below is a C++-class hierarchy used in this code
+base.  They are explained further in the READMEs in their respective direc-
+tories, so the file names where the classes are defined is listed below (this,
+very roughly in order of functional interactions, of chronological usage during
+execution, and of most-to-least importance):
+
+    template_line                        ./template/template_line.hpp
+        sst_template_line                ./template/template_line.hpp
+            read_sst_template_line       ./template/sst_template_line.hpp
+            remove_sst_template_line     ./template/sst_template_line.hpp
+            set_sst_template_line        ./template/sst_template_line.hpp
+        policy_template_line             ./template/template_line.hpp
+            read_policy_template_line    ./template/crypto_template_line.hpp
+            set_policy_template_line     ./template/crypto_template_line.hpp
+        key_template_line                ./template/template_line.hpp
+            read_key_template_line       ./template/crypto_template_line.hpp
+            remove_key_template_line     ./template/crypto_template_line.hpp
+            set_key_template_line        ./template/crypto_template_line.hpp
+        security_template_line           ./template/template_line.hpp
+            security_hash_template_line  ./template/secure_template_line.hpp
+
+    psa_call                             ./calls/psa_call.hpp
+        crypto_call                      ./calls/psa_call.hpp
+            policy_call                  ./calls/crypto_call.hpp
+                policy_get_call          ./calls/crypto_call.hpp
+                policy_set_call          ./calls/crypto_call.hpp
+            key_call                     ./calls/crypto_call.hpp
+                get_key_info_call        ./calls/crypto_call.hpp
+                set_key_call             ./calls/crypto_call.hpp
+                destroy_key_call         ./calls/crypto_call.hpp
+        sst_call                         ./calls/psa_call.hpp
+            sst_remove_call              ./calls/sst_call.hpp
+            sst_get_call                 ./calls/sst_call.hpp
+            sst_set_call                 ./calls/sst_call.hpp
+        security_call                    ./calls/psa_call.hpp
+            hash_call                    ./calls/security_call.hpp
+
+    boilerplate                          ./boilerplate/boilerplate.hpp
+
+    psa_asset                            ./assets/psa_asset.hpp
+        crypto_asset                     ./assets/crypto_asset.hpp
+            policy_asset                 ./assets/crypto_asset.hpp
+            key_asset                    ./assets/crypto_asset.hpp
+        sst_asset                        ./assets/sst_asset.hpp
+
+    tf_fuzz_info                         ./tf_fuzz.hpp
+
+    crc32                                ./utility/compute.hpp
+
+    gibberish                            ./utility/gibberish.hpp
+
+    expect_info                          ./utility/data_blocks.hpp
+    set_data_info                        ./utility/data_blocks.hpp
+    asset_name_id_info                   ./utility/data_blocks.hpp
+
+--------------------------------------------------------------------------------
+
+There are currently two especially annoying warts on the design of TF-Fuzz:
+*   Need better management of variables in the generated code.  Currently,
+    for example, upon "read"ing a value from a PSA asset more than once, it
+    creates a same-named (i.e., duplicate) variable for each such time, which
+    is obviously not right.
+*   Upon adding the ability to do "do any N of these PSA calls at random,"
+    in hindsight, a fundamental flaw was uncovered in the top-level flow of
+    how TF-Fuzz generates the code.  High-level summary:
+  *   It should have completely distinct Parse, Simulate, then Code-generation
+      stages.
+  *   Currently, the Parse and Simulate stages aren't really completely
+      distinct, so there's a bunch of complicated Boolean flags traffic-
+      copping between what in hindsight should be completely-separate Parse
+      vs. Code-generation functionality.
+    The function, interpret_template_line(), currently in
+    .../tf_fuzz/parser/tf_fuzz_grammar.y (which may be moved to the its own file
+    with randomize_template_lines()), has the lion's share of such Booleans,
+    such as fill_in_template, create_call_bool, and create_asset_bool.
+    The way it *should* work is:
+  *   The parser in .../tf_fuzz_grammar.y should generate an STL vector (or
+      list) of psa_call-subclass "tracker" objects.  It should not generate
+      PSA-asset tracker objects (subclasses of psa_asset).
+  *   There should then be an organized Simulate stage, that sequences through
+      the psa_call-subclass list, creating and accumulating/maintaining current
+      state in psa_asset-subclass objects, using that current state to
+      determine expected results of each PSA call, which get annotated back
+      into the psa_call-tracker objects.
+  *   Finally, there already is, and should continue to be, a Code-generation
+      phase that writes out the code, based upon text substitutions of
+      "boilerplate" code snippets.
+  *   Currently, (hindsight obvious) the Parse and Simulate phases got somewhat
+      muddled together.  This shouldn't be super-hard to fix.
+    That final Code-generation phase, conceptually at least, could be replaced
+    instead with simply executing those commands directly, for targets that
+    sufficient space to run TF-Fuzz in real-time.
+
+--------------
+
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
diff --git a/tools/tf_fuzz/assets/README b/tools/tf_fuzz/assets/README
new file mode 100644
index 0000000..d5f0a0a
--- /dev/null
+++ b/tools/tf_fuzz/assets/README
@@ -0,0 +1,19 @@
+.../tf_fuzz/assets directory contents:
+
+crypto_asset.cpp  psa_asset.cpp  sst_asset.cpp
+crypto_asset.hpp  psa_asset.hpp  sst_asset.hpp
+
+--------------------------------------------------------------------------------
+
+This directory contains C++ header and program files for classes of objects that
+track PSA assets, notably during the Simulate phase.
+
+These hold current state of those assets as the run is simulated, after the
+exact sequence of PSA commands to be executed is generated by the Parse stage.
+
+Currently, the Simulate stage, which should be completely distinct from the
+initial Parse stage, in hindsight, is a bit muddled up with the Parse stage.
+
+--------------
+
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
diff --git a/tools/tf_fuzz/assets/crypto_asset.cpp b/tools/tf_fuzz/assets/crypto_asset.cpp
new file mode 100644
index 0000000..fcb57a4
--- /dev/null
+++ b/tools/tf_fuzz/assets/crypto_asset.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "class_forwards.hpp"
+
+#include "boilerplate.hpp"
+#include "randomization.hpp"
+#include "gibberish.hpp"
+#include "compute.hpp"
+#include "data_blocks.hpp"
+#include "psa_asset.hpp"
+#include "find_or_create_asset.hpp"
+#include "template_line.hpp"
+#include "tf_fuzz.hpp"
+#include "crypto_asset.hpp"
+#include "psa_call.hpp"
+
+
+
+/**********************************************************************************
+   Methods of class crypto_asset follow:
+**********************************************************************************/
+
+crypto_asset::crypto_asset (void)  // (default constructor)
+{
+    return;  // just to have something to pin a breakpoint onto
+}
+
+
+crypto_asset::~crypto_asset (void)  // (destructor)
+{
+    return;  // just to have something to pin a breakpoint onto
+}
+
+/**********************************************************************************
+   End of methods of class crypto_asset.
+**********************************************************************************/
+
+
+/**********************************************************************************
+   Methods of class policy_asset follow:
+**********************************************************************************/
+
+policy_asset::policy_asset (void)  // (default constructor)
+{
+    // Randomize key-policy usage and algorithm:
+    policy_usage = rand_key_usage();
+    policy_algorithm = rand_key_algorithm();
+    // keys:  Should automatically come up as empby.
+}
+
+
+policy_asset::~policy_asset (void)  // (destructor)
+{
+    return;  // just to have something to pin a breakpoint onto
+}
+
+/**********************************************************************************
+   End of methods of class policy_asset.
+**********************************************************************************/
+
+
+/**********************************************************************************
+   Methods of class key_asset follow:
+**********************************************************************************/
+
+bool key_asset::set_key_id (int id_n)
+{
+    key_id = id_n;
+    return true;
+}
+
+
+key_asset::key_asset (void)
+{
+    // Note:  Similar random initialization for asset and template
+    // Randomize handle:
+    // TODO:  Key handles appear to be a lot more complex a question than the below
+    string wrong_data;  // temporary for initial random to be overwritten
+    gibberish *gib = new gibberish;
+    handle_str = gib->word (false, const_cast<char*>(wrong_data.c_str()),
+                            const_cast<char*>(wrong_data.c_str()) + data.length()-1);
+    // Randomize key type:
+    key_type = rand_key_type();
+    // Randomize lifetime:
+    lifetime_str = ((rand() % 2) == 1)?
+                       "PSA_KEY_LIFETIME_VOLATILE" : "PSA_KEY_LIFETIME_PERSISTENT";
+}
+
+
+key_asset::~key_asset (void)
+{
+    return;  // just to have something to pin a breakpoint onto
+}
+
+/**********************************************************************************
+   End of methods of class key_asset.
+**********************************************************************************/
diff --git a/tools/tf_fuzz/assets/crypto_asset.hpp b/tools/tf_fuzz/assets/crypto_asset.hpp
new file mode 100644
index 0000000..d1d7235
--- /dev/null
+++ b/tools/tf_fuzz/assets/crypto_asset.hpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef CRYPTO_ASSET_HPP
+#define CRYPTO_ASSET_HPP
+
+#include <string>
+#include <vector>
+#include <cstddef>
+#include <cstdint>
+
+
+/* This project's header files #including other project headers quickly becomes
+   unrealistically complicated.  The only solution is for each .cpp to include
+   the headers it needs.
+#include "psa_asset.hpp"
+*/
+
+
+using namespace std;
+
+class crypto_asset : public psa_asset
+{
+public:
+    // Data members:
+    // Methods:
+        crypto_asset (void);  // (constructor)
+        ~crypto_asset (void);
+
+protected:
+    // Data members:
+    // Methods:
+
+private:
+    // Data members:
+    // Methods:
+};
+
+class policy_asset : public crypto_asset
+{
+public:
+    // Data members:
+        string policy_usage;  // for now just strings;  maybe future tap TF-M(?) value list
+        string key_type;  // DES, AES, RAW, vendor, none, etc.
+        string policy_algorithm;
+        vector<key_asset*> keys;  // keys that use this policy
+    // Methods:
+        policy_asset (void);  // (constructor)
+        ~policy_asset (void);
+
+protected:
+    // Data members:
+    // Methods:
+
+private:
+    // Data members:
+    // Methods:
+};
+
+class key_asset : public crypto_asset
+{
+public:
+    // Data members:
+        vector<policy_asset*>::iterator the_policy_asset;
+            /* The policy for this key.  Note that psa_make_key() lets us create
+             a key without associating a policy with it.  In that case, this will
+             be null, and the attributes below apply.  Later, psa_set_key_policy
+             lets us associate a policy with a key, at which point this becomes
+             non-null and the following attributes no longer apply. */
+        string key_type;  // DES, AES, RAW, vendor, none, etc.
+        string usage;  // for now just strings;  maybe future tap TF-M(?) value list
+        string alg;  // these only apply if the string was created without a policy
+        string lifetime_str;  // similarly, the text representation of the key's lifetime
+        string handle_str;  // the text name of the key's "handle"
+    // Methods:
+        bool set_key_id (int id_n);  // checks key-ID value, returns true==success
+        key_asset (void);  // (constructor)
+        ~key_asset (void);
+
+protected:
+    // Data members:
+        uint64_t key_id;
+    // Methods:
+
+private:
+    // Data members:
+    // Methods:
+};
+
+#endif  // CRYPTO_ASSET_HPP
diff --git a/tools/tf_fuzz/assets/psa_asset.cpp b/tools/tf_fuzz/assets/psa_asset.cpp
new file mode 100644
index 0000000..d5bed08
--- /dev/null
+++ b/tools/tf_fuzz/assets/psa_asset.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "class_forwards.hpp"
+
+#include "boilerplate.hpp"
+#include "gibberish.hpp"
+#include "compute.hpp"
+#include "data_blocks.hpp"
+#include "psa_asset.hpp"
+#include "find_or_create_asset.hpp"
+#include "template_line.hpp"
+#include "tf_fuzz.hpp"
+#include "crypto_asset.hpp"
+#include "psa_call.hpp"
+
+
+/**********************************************************************************
+   Methods of class psa_asset follow:
+**********************************************************************************/
+
+void psa_asset::set_name (string set_val)
+{
+    asset_id.name_specified = true;
+    asset_name.assign (set_val);
+}
+
+string psa_asset::get_name (void)
+{
+    return asset_name;
+}
+
+psa_asset::psa_asset (void)  // (default constructor)
+{
+    asset_ser_no = unique_id_counter++;  // just something to pin a breakpoint onto
+}
+
+
+psa_asset::~psa_asset (void)
+{
+    return;  // just to have something to pin a breakpoint onto
+}
+
+/**********************************************************************************
+   End of methods of class psa_asset.
+**********************************************************************************/
diff --git a/tools/tf_fuzz/assets/psa_asset.hpp b/tools/tf_fuzz/assets/psa_asset.hpp
new file mode 100644
index 0000000..94c7ddf
--- /dev/null
+++ b/tools/tf_fuzz/assets/psa_asset.hpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef PSA_ASSET_HPP
+#define PSA_ASSET_HPP
+
+#include <string>
+#include <vector>
+#include <cstdint>
+
+/* 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. */
+
+using namespace std;
+
+class psa_asset
+{
+public:
+    /* Data members -- not all PSA assets have all of these, but they need to be
+       accessible polymorphically via a psa_asset iterator: */
+        set_data_info set_data;
+            /* For a PSA-asset tracker, this is really more about an asset's
+               on-going, real-time asset data value than about *setting* its data
+               value.  On a template_line or a psa_call, it's about setting its
+               value at one particular time. */
+        asset_name_id_info asset_id;  // everything about the asset(s) for this line
+        vector<int> template_ref;
+            // list of template line #s that reference this asset
+        vector<psa_call> call_ref;  // list of PSA calls that reference this asset
+        string handle_str;  // the text name of the key's "handle"
+        string flags_string;  // creation flags
+        long asset_ser_no;
+            // unique serial# for this psa_asset; see note in tf_fuzz.hpp
+        bool asset_name_specified;
+            /* true if the template specified the asset_name, as opposed to us
+               having inferred it. */
+    // Methods:
+        void set_name (string set_val);
+        string get_name (void);
+        psa_asset();  // (constructor)
+        ~psa_asset();
+
+protected:
+    // Data members:
+        // These are initially copied over from the call (or possibly template line):
+        string data;  // String describing current data value.
+        string asset_name;  // human-meaningful name
+        static long unique_id_counter;  // counts off unique IDs for assets
+    // Methods:
+
+private:
+    // Data members:
+    // Methods:
+};
+
+#endif  // PSA_ASSET_HPP
diff --git a/tools/tf_fuzz/assets/sst_asset.cpp b/tools/tf_fuzz/assets/sst_asset.cpp
new file mode 100644
index 0000000..8b482eb
--- /dev/null
+++ b/tools/tf_fuzz/assets/sst_asset.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "class_forwards.hpp"
+
+#include "boilerplate.hpp"
+#include "gibberish.hpp"
+#include "compute.hpp"
+#include "data_blocks.hpp"
+#include "psa_asset.hpp"
+#include "find_or_create_asset.hpp"
+#include "template_line.hpp"
+#include "tf_fuzz.hpp"
+#include "crypto_asset.hpp"
+#include "psa_call.hpp"
+#include "sst_asset.hpp"
+
+
+
+/**********************************************************************************
+   Methods of class sst_asset follow:
+**********************************************************************************/
+
+bool sst_asset::set_uid (uint64_t uid)
+{
+    /* TODO:  What are the limits upon UIDs?  I don't necessarily not want to be
+              able to set an illegal value, but if it is illegal, I might want to
+              set some flag appropriately to generate expected results. */
+    asset_id.set_id_n (uid);
+    return true;
+}
+
+sst_asset::sst_asset (void)  // (default constructor)
+{
+    return;  // just to have something to pin a breakpoint onto
+}
+
+
+sst_asset::~sst_asset (void)  // (destructor)
+{
+    return;  // just to have something to pin a breakpoint onto
+}
+
+/**********************************************************************************
+   End of methods of class sst_asset.
+**********************************************************************************/
diff --git a/tools/tf_fuzz/assets/sst_asset.hpp b/tools/tf_fuzz/assets/sst_asset.hpp
new file mode 100644
index 0000000..0fbd5b8
--- /dev/null
+++ b/tools/tf_fuzz/assets/sst_asset.hpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef SST_ASSET_HPP
+#define SST_ASSET_HPP
+
+#include <string>
+
+/* This project's header files #including other project headers quickly becomes
+   unrealistically complicated.  The only solution is for each .cpp to include
+   the headers it needs.
+#include "psa_asset.hpp"
+*/
+
+
+using namespace std;
+
+class sst_asset : public psa_asset
+{
+public:  // (low value in hiding these behind setters and getters)
+    // Data members:
+    // Methods:
+        bool set_uid (uint64_t uid);  // checks input UID value, returns true==success
+        void set_literal_data (string literal_data);
+           // if literal data, this sets both "data" string and "data_length"
+        sst_asset (void);  // (constructor)
+        ~sst_asset (void);
+
+protected:
+    // Data members:
+    // Methods:
+
+private:
+    // Data members:
+    // Methods:
+};
+
+#endif  // SST_ASSET_HPP
diff --git a/tools/tf_fuzz/boilerplate/README b/tools/tf_fuzz/boilerplate/README
new file mode 100644
index 0000000..6bca158
--- /dev/null
+++ b/tools/tf_fuzz/boilerplate/README
@@ -0,0 +1,17 @@
+.../tf_fuzz/boilerplate directory contents:
+
+boilerplate.cpp  boilerplate.hpp
+
+--------------------------------------------------------------------------------
+
+These are the C++ code to work with the customizable, "boilerplate" code
+snippets in the .../lib directory.  Actually, mostly what this code does is
+read these code snippets into an STL vector of, essentially, named strings.
+
+This is currently implemented as a vector of strings, with a parallel vector
+of const int array-index names.  A much better way, in hindsight, to manage
+the boilerplate code is in an STL "map" container.
+
+--------------
+
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
diff --git a/tools/tf_fuzz/boilerplate/boilerplate.cpp b/tools/tf_fuzz/boilerplate/boilerplate.cpp
new file mode 100644
index 0000000..60deab7
--- /dev/null
+++ b/tools/tf_fuzz/boilerplate/boilerplate.cpp
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "class_forwards.hpp"
+
+#include "boilerplate.hpp"
+#include "gibberish.hpp"
+#include "compute.hpp"
+#include "data_blocks.hpp"
+#include "psa_asset.hpp"
+#include "find_or_create_asset.hpp"
+#include "template_line.hpp"
+#include "tf_fuzz.hpp"
+#include "crypto_asset.hpp"
+#include "psa_call.hpp"
+
+/**********************************************************************************
+   Methods of class boilerplate follow:
+**********************************************************************************/
+
+void env_var_usage (void)
+{
+    cerr << "Example, for typical TF-M usage, using bash syntax:" << endl
+         << "   export TF_FUZZ_LIB_DIR=<path to TF-M installation>/tools/tf_fuzz/lib"
+         << endl
+         << "   export TF_FUZZ_BPLATE=tfm_boilerplate.txt" << endl;
+}
+
+void boilerplate::stuff_boilerplate_strings (void)
+{
+    ifstream boilerplate_lib;
+    string file_name;  // boilerplate file name
+    string holder;
+        // temp string, e.g., holder for strings read from the boilerplate file
+
+    /* User must point the environment variable $TF_FUZZ_BPLATE to the boilerplate
+       file s/he wants to use, within a directory named by $TF_FUZZ_LIB_DIR. */
+    string bpStringL, bpStringF;
+    char *bpLibDir = getenv ("TF_FUZZ_LIB_DIR");
+    if (bpLibDir == NULL) {
+        cerr << "Error:  Please point environment variable $TF_FUZZ_LIB_DIR to "
+             << "TF-Fuzz's library directory." << endl;
+        env_var_usage();
+        exit (701);
+    }
+    bpStringL = bpLibDir;
+    char *bpFName = getenv ("TF_FUZZ_BPLATE");
+    if (bpFName == NULL) {
+        cerr << "Error:  Please set environment variable $TF_FUZZ_BPLATE to name the "
+             << "\"boilerplate\" text-library file." << endl;
+        env_var_usage();
+        exit (702);
+    }
+    bpStringF = bpFName;
+    file_name.assign (bpStringL + "/" + bpStringF);
+    boilerplate_lib.open (file_name);
+    if (!boilerplate_lib.is_open()) {
+        cerr << "\nError:  Unable to open boilerplate text-library file, at path "
+             << file_name << "." << endl;
+        env_var_usage();
+        exit(200);
+    }
+
+    // Read the strings into the boilerplate vector:
+    getline (boilerplate_lib, holder, '`');
+        /* This first one is "not real."  It's a README, in essence, explaining the
+           library-text file, so skip past it. */
+    for (int i = preamble_A;  i < n_boilerplate_texts;  i++) {
+        if (!getline (boilerplate_lib, holder, '`')) {
+            cerr << "\nError:  Unable to read from boilerplate text-library file, at path "
+                 << file_name << "." << endl;
+            cerr << "        Please make sure the file is not empty." << endl;
+            env_var_usage();
+            exit(851);
+        }
+        if (holder.length() < 5) {
+            cerr << "\nError:  Read from boilerplate text-library file, at path "
+                 << file_name << ", was too short." << endl;
+            cerr << "        Please make sure the file has not been damaged "
+                 << "from the TF-Fuzz distribution." << endl;
+            env_var_usage();
+            exit(852);
+        }
+        // Shave off the three-character tag + \n from the front of the string:
+        holder.erase(0, 4);
+        bplate_string.push_back(holder);
+    }
+    boilerplate_lib.close();
+}
+
+boilerplate::boilerplate (void) {
+    stuff_boilerplate_strings();
+}
+
+/**********************************************************************************
+   End of methods of class boilerplate.
+**********************************************************************************/
diff --git a/tools/tf_fuzz/boilerplate/boilerplate.hpp b/tools/tf_fuzz/boilerplate/boilerplate.hpp
new file mode 100644
index 0000000..0877f3e
--- /dev/null
+++ b/tools/tf_fuzz/boilerplate/boilerplate.hpp
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/* boilerplate.*pp contains class(es) to read and store customizable code
+   fragments used in realizing the pieces of a test.  It's critical that
+   these be customizable in external library files, so that TF-Fuzz can
+   exercise TF-A as well as TF-M.  Each TF-x has its own library of text
+   pieces, which are read into these data structures upon program initial-
+   ization. */
+
+#ifndef BOILERPLATE_HPP
+#define BOILERPLATE_HPP
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+
+
+using namespace std;
+
+// Constant mnemonics for entries in array of boilerplate texts:
+const int
+    // Stuff around the test itself:
+        preamble_A = 0,  // setup stuff before PSA calls begin
+            /* Strings to be substituted from template:
+            $purpose:  The purpose of the test */
+        hashing_code = 1,  // code to perform a simple hash of asset data
+            /* Strings to be substituted from template:  (none) */
+        preamble_B = 2,  // setup stuff before PSA calls begin
+            /* Strings to be substituted from template:
+            $purpose:  The purpose of the test */
+        declare_int = 3,  // declaration for an int
+            /* Strings to be substituted from template:
+            $var:  The integer thing to declare
+            $init:  Its initialization */
+        declare_string = 4,  // declaration for a string
+            /* Strings to be substituted from template:
+            $var:  The string variable to declare
+            $init:  Its initialization */
+        declare_big_string = 5,  // declaration for a string, sized large
+            /* Strings to be substituted from template:
+            $var:  The string variable to declare
+            $init:  Its initialization */
+        declare_generic = 6,  // declaration for a some other type
+            /* Strings to be substituted from template:
+            $type:  The type to declare the variable to
+            $var:  The string variable to declare
+            $init:  Its initialization */
+        test_log = 7,  // print a message to the test log
+            /* Strings to be substituted from template:
+            $message:  What to print. */
+        teardown_sst = 8,  // call to delete SST resources after test completes
+            /* Strings to be substituted from template:
+              $uid:  (Exactly that) */
+        teardown_sst_check = 9,  // boilerplate code to check success of previous;
+            /* No strings to be substituted from template */
+        teardown_key = 10,  // call to delete crypto keys after test completes
+            /* Strings to be substituted from template:
+              $handle:  The handle to the key */
+        teardown_key_check = 11,  // boilerplate code to check success of previous;
+            /* No strings to be substituted from template */
+        closeout = 12,  // final code to close out the test.
+            // No strings to substitute.
+        sst_pass_string = 13,  // passing SST expected result
+        sst_fail_removed = 14,  // SST expected result from having deleted the asset
+    // SST calls:
+        set_sst_call = 15,  // boilerplate for setting up an SST asset;
+            /* Strings to be substituted from template:
+              $op:  (for comment) either "Creating" or "Resetting"
+              $description:  its "human name" if given, or "UID=..." if not
+              $data_source:  either first ~10 chars of data or file path
+              $uid:  (Exactly that)
+              $length:  Data length
+              $data:  Pointer to data (C string)
+              $flags:  SST-asset creation flags */
+        set_sst_check = 16,  // boilerplate code to check success of previous;
+            /* Strings to be substituted from template:
+              $expect:  Expected return status string */
+        get_sst_call = 17,  // boilerplate for retrieving data from an SST asset;
+            /* Strings to be substituted from template:
+              $uid:  (Exactly that)
+              $offset:  Start positon in the "file"  TO DO:  ADD OFFSET
+              $length:  Data length
+              $act_data:  Pointer to actual data (C string) */
+        get_sst_check = 18,  // boilerplate code to check call result only;
+            /* Strings to be substituted from template:
+              $expect:  Expected return status string */
+        get_sst_check_all = 19,  // boilerplate code to check call result and data;
+            /* Strings to be substituted from template:
+              $expect:  Expected return status
+              $exp_data:  Expected read data
+              $act_data:  Actual read data
+              $length:  Data length */
+        get_sst_hash = 20,  // boilerplate code to invoke hasher;
+            /* Strings to be substituted from template:
+              $act_data_var:  Actual read data, to be hashed
+              $hash_var:  Hash-result variable */
+        remove_sst = 21,  // boilerplate for removing an SST asset;
+            /* Strings to be substituted from template:
+              $uid:  (Exactly that) */
+        remove_sst_check = 22,  // boilerplate code to check success of previous;
+            /* Strings to be substituted from template:
+              $expect:  Expected return status */
+    // Crypto-key-policy calls:
+        set_policy = 23,  // boilerplate for setting up a key policy;
+            /* Strings to be substituted from template:
+              $policy:  The key-policy to define
+              $usage:  The key-policy usage
+              $alg:  The key-policy algorithm */
+        set_policy_check = 24,  // boilerplate code to check success of previous;
+            /* Strings to be substituted from template:
+              $expect:  Expected return status */
+        get_policy = 25,  // boilerplate for retrieving data from a key policy;
+            /* Strings to be substituted from template:
+              $policy:  The key-policy to view */
+        get_policy_check = 26,  // boilerplate code to check success of previous;
+            /* Strings to be substituted from template:
+              $expect:  Expected return status */
+    // Crypto-key-related calls:
+        set_key = 27,  // boilerplate for setting up a key;
+            /* Strings to be substituted from template:
+              $lifetime:  The lifetime of the key
+              $handle:  The handle to the key */
+        set_key_check = 28,  // boilerplate code to check success of previous;
+            /* Strings to be substituted from template:
+              $expect:  Expected return status */
+        get_key = 29,  // boilerplate for retrieving data from a key;
+            /* Strings to be substituted from template:
+              $handle:  The handle to the key
+              $type:  The returned key type
+              $bits:  The returned size in bits */
+        get_key_check = 30,  // boilerplate code to check success of previous;
+            /* Strings to be substituted from template:
+              $expect:  Expected return status */
+        get_key_check_n_bits = 31,
+            /* Strings to be substituted from template:
+              $n_bits:  returned #bits (actually just left side of if (a!=b)
+              $m_bits:  expected #bits (actually just right side of if (a!=b) */
+        remove_key = 32,  // boilerplate for creating a key;
+            /* Strings to be substituted from template:
+              $handle:  The handle to the key */
+        remove_key_check = 33,  // boilerplate code to check success of previous;
+            /* Strings to be substituted from template:
+              $expect:  Expected return status */
+    // Just an anchor at the end, for sizing the string array (if needed):
+        n_boilerplate_texts = 34;
+
+
+class boilerplate
+{
+public:  // (More pain than it's worth to create getters and setters)
+    // Data members:
+    vector<string> bplate_string;
+    string cpp_string;  // used to stuff bplate_string
+    // Methods:
+    void stuff_boilerplate_strings (void);
+    boilerplate (void);
+};
+
+
+#endif  // #ifndef BOILERPLATE_HPP
diff --git a/tools/tf_fuzz/calls/README b/tools/tf_fuzz/calls/README
new file mode 100644
index 0000000..e9f9c39
--- /dev/null
+++ b/tools/tf_fuzz/calls/README
@@ -0,0 +1,16 @@
+.../tf_fuzz/calls directory contents:
+
+crypto_call.cpp  psa_call.cpp  security_call.cpp  sst_call.cpp
+crypto_call.hpp  psa_call.hpp  security_call.hpp  sst_call.hpp
+
+--------------------------------------------------------------------------------
+
+These classes define objects that describe everything needed to generate a PSA
+call.  In the future, it's probably possible to, instead of writing these calls
+out to a .c file, for target systems that can support sufficiently large memory
+footprints, to directly execute these PSA calls from the psa_call-subclass
+"tracker" objects.
+
+--------------
+
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
diff --git a/tools/tf_fuzz/calls/crypto_call.cpp b/tools/tf_fuzz/calls/crypto_call.cpp
new file mode 100644
index 0000000..ffc5ed3
--- /dev/null
+++ b/tools/tf_fuzz/calls/crypto_call.cpp
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <cstdlib>
+
+#include "class_forwards.hpp"
+
+#include "boilerplate.hpp"
+#include "gibberish.hpp"
+#include "compute.hpp"
+#include "randomization.hpp"
+#include "string_ops.hpp"
+#include "data_blocks.hpp"
+#include "psa_asset.hpp"
+#include "find_or_create_asset.hpp"
+#include "template_line.hpp"
+#include "tf_fuzz.hpp"
+#include "crypto_asset.hpp"
+#include "psa_call.hpp"
+#include "crypto_call.hpp"
+#include "sst_asset.hpp"
+
+
+
+/**********************************************************************************
+   Methods of class policy_call follow:
+**********************************************************************************/
+
+policy_call::policy_call (tf_fuzz_info *test_state,    // (constructor)
+                          long &call_ser_no,
+                          asset_search how_asset_found)
+                             : crypto_call(test_state, call_ser_no, how_asset_found)
+{
+    // Randomize key-policy usage and algorithm:
+    policy_usage = rand_key_usage();
+    policy_algorithm = rand_key_algorithm();
+}
+policy_call::~policy_call (void)
+{
+    // Nothing further to delete.
+    return;  // just to have something to pin a breakpoint onto
+}
+
+/**********************************************************************************
+   End of methods of class policy_call.
+**********************************************************************************/
+
+
+/**********************************************************************************
+   Methods of class key_call follow:
+**********************************************************************************/
+
+key_call::key_call (tf_fuzz_info *test_state,    // (constructor)
+                          long &call_ser_no,
+                          asset_search how_asset_found)
+                             : crypto_call(test_state, call_ser_no, how_asset_found)
+{
+    // Note:  Similar random initialization for asset and template.
+    // Randomize handle:
+    // TODO:  Key handles appear to be a lot more complex a question than the below.
+    string wrong_data;
+    gibberish *gib = new gibberish;
+    handle_str = gib->word (false, const_cast<char*>(wrong_data.c_str()),
+                            const_cast<char*>(wrong_data.c_str())
+                                                        + set_data.get().length()-1);
+    // Randomize key type:
+    key_type = rand_key_type();
+    // Randomize lifetime:
+    lifetime_str = ((rand() % 2) == 1)?
+                       "PSA_KEY_LIFETIME_VOLATILE" : "PSA_KEY_LIFETIME_PERSISTENT";
+    // Choose a random expected key size in bits:
+    expected_n_bits = to_string(rand()%10000);
+    delete gib;
+}
+key_call::~key_call (void)
+{
+    // Nothing further to delete.
+    return;  // just to have something to pin a breakpoint onto
+}
+
+/**********************************************************************************
+   End of methods of class key_call.
+**********************************************************************************/
+
+
+/**********************************************************************************
+   Methods of class policy_set_call follow:
+**********************************************************************************/
+
+policy_set_call::policy_set_call (tf_fuzz_info *test_state,    // (constructor)
+                                  long &call_ser_no,
+                                  asset_search how_asset_found)
+                                     : policy_call(test_state, call_ser_no,
+                                                   how_asset_found)
+{
+    // Copy the boilerplate text into local buffers:
+    prep_code.assign ("");
+    call_code.assign (test_state->bplate->bplate_string[set_policy]);
+    check_code.assign (test_state->bplate->bplate_string[set_policy_check]);
+}
+policy_set_call::~policy_set_call (void)
+{
+    // Nothing further to delete.
+    return;  // just to have something to pin a breakpoint onto
+}
+
+void policy_set_call::fill_in_prep_code (void)
+{
+    // No prep code required.
+    return;  // just to have something to pin a breakpoint onto
+}
+
+void policy_set_call::fill_in_command (void)
+{
+    vector<psa_asset*>::iterator found_asset;
+
+    // Is this search really needed?
+    // Find the call by serial number (must search;  may have moved).
+    how_asset_found = test_state->find_or_create_policy_asset (
+                                      psa_asset_search::serial, psa_asset_usage::all,
+                                      "", 0, asset_ser_no,
+                                      yes_create_asset, found_asset );
+    if (how_asset_found == asset_search::unsuccessful) {
+        cerr << "\nError:  Tool-internal:  TF-Fuzz failed to find a required asset."
+             << endl;
+        exit(103);
+    }
+    string var_name = asset_id.get_name() + "_data";
+    string id_string = to_string((long) asset_id.id_n);
+    // Fill in the PSA command itself:
+    find_replace_1st ("$policy", id_string, call_code);
+    find_replace_1st ("$usage", policy_usage, call_code);
+    find_replace_1st ("$alg", policy_algorithm, call_code);
+    // Figure out what expected results:
+    calc_result_code();
+}
+
+/**********************************************************************************
+   End of methods of class policy_set_call.
+**********************************************************************************/
+
+
+/**********************************************************************************
+   Methods of class policy_get_call follow:
+**********************************************************************************/
+
+policy_get_call::policy_get_call (tf_fuzz_info *test_state,    // (constructor)
+                                  long &call_ser_no,
+                                  asset_search how_asset_found)
+                                     : policy_call(test_state, call_ser_no,
+                                                   how_asset_found)
+{
+    // Copy the boilerplate text into local buffers:
+    prep_code.assign ("");
+    call_code.assign (test_state->bplate->bplate_string[get_policy]);
+    check_code.assign (test_state->bplate->bplate_string[get_policy_check]);
+}
+policy_get_call::~policy_get_call (void)
+{
+    return;  // just to have something to pin a breakpoint onto
+}
+
+void policy_get_call::fill_in_prep_code (void)
+{
+    return;  // just to have something to pin a breakpoint onto
+}
+
+void policy_get_call::fill_in_command (void)
+{
+    find_replace_1st ("$policy", id_string, call_code);
+    // Figure out what expected results:
+// TODO:  Make data checks contingent upon the PSA call itself passing!
+    calc_result_code();
+    // TODO:  DOESN'T SOMETHING HAVE TO CHECK THE ALGORITHM AND USAGE (perhaps that's a different call)?
+}
+
+/**********************************************************************************
+   End of methods of class policy_get_call.
+**********************************************************************************/
+
+
+/**********************************************************************************
+   Methods of class set_key_call follow:
+**********************************************************************************/
+
+set_key_call::set_key_call (tf_fuzz_info *test_state,    // (constructor)
+                                  long &call_ser_no,
+                                  asset_search how_asset_found)
+                                     : key_call(test_state, call_ser_no,
+                                                how_asset_found)
+{
+    // Copy the boilerplate text into local buffers:
+    prep_code.assign (test_state->bplate->bplate_string[declare_generic]);
+    call_code.assign (test_state->bplate->bplate_string[set_key]);
+    check_code.assign (test_state->bplate->bplate_string[set_key_check]);
+}
+set_key_call::~set_key_call (void)
+{
+}
+
+void set_key_call::fill_in_prep_code (void)
+{
+    // Create declaration of lifetime's holder variable:
+    find_replace_1st ("$type", "psa_key_lifetime_t", prep_code);
+    find_replace_1st ("$var", handle_str + "_lifetime", prep_code);
+    find_replace_1st ("$init", lifetime_str, prep_code);
+}
+
+void set_key_call::fill_in_command (void)
+{
+    find_replace_1st ("$lifetime", handle_str + "_lifetime", call_code);
+    find_replace_1st ("$handle", handle_str, call_code);
+    // Figure out what expected results:
+    calc_result_code();
+}
+
+/**********************************************************************************
+   End of methods of class set_key_call.
+**********************************************************************************/
+
+
+/**********************************************************************************
+   Methods of class get_key_info_call follow:
+**********************************************************************************/
+
+get_key_info_call::get_key_info_call (tf_fuzz_info *test_state,    // (constructor)
+                                      long &call_ser_no,
+                                      asset_search how_asset_found)
+                                         : key_call(test_state, call_ser_no,
+                                                    how_asset_found)
+{
+    // Copy the boilerplate text into local buffers:
+    prep_code.assign (test_state->bplate->bplate_string[declare_generic]);
+    call_code.assign (test_state->bplate->bplate_string[get_key]);
+    check_code.assign (test_state->bplate->bplate_string[get_key_check]);
+}
+get_key_info_call::~get_key_info_call (void)
+{
+}
+
+void get_key_info_call::fill_in_prep_code (void)
+{
+    // Create declaration of size_t variable to accept #bits info into:
+    find_replace_1st ("$type", "size_t", prep_code);
+    find_replace_1st ("$var", handle_str + "_n_bits", prep_code);
+    find_replace_1st ("$init", to_string(rand()%10000), prep_code);
+}
+
+void get_key_info_call::fill_in_command (void)
+{
+    // The call itself:
+    find_replace_1st ("$handle", handle_str + "_lifetime", call_code);
+    find_replace_1st ("$type", key_type, call_code);
+    find_replace_1st ("$bits", handle_str + "_n_bits", call_code);
+    // Figure out what expected return code:
+    calc_result_code();
+    // But also need to write code to check #bits returned:
+    if (!expect.pf_nothing) {
+// TODO:  Make data checks contingent upon the PSA call itself passing!
+        call_code.append (test_state->bplate->bplate_string[get_key_check_n_bits]);
+        find_replace_1st ("$n_bits", handle_str + "_n_bits", check_code);
+        find_replace_1st ("$m_bits", expected_n_bits, check_code);
+    }
+}
+
+/**********************************************************************************
+   End of methods of class get_key_info_call.
+**********************************************************************************/
+
+
+/**********************************************************************************
+   Methods of class destroy_key_call follow:
+**********************************************************************************/
+
+destroy_key_call::destroy_key_call (tf_fuzz_info *test_state,    // (constructor)
+                                    long &call_ser_no,
+                                    asset_search how_asset_found)
+                                        : key_call(test_state, call_ser_no,
+                                                   how_asset_found)
+{
+    // Copy the boilerplate text into local buffers:
+    prep_code.assign ("");
+    call_code.assign (test_state->bplate->bplate_string[remove_key]);
+    check_code.assign (test_state->bplate->bplate_string[remove_key_check]);
+}
+destroy_key_call::~destroy_key_call (void)
+{
+    return;  // just to have something to pin a breakpoint onto
+}
+
+void destroy_key_call::fill_in_prep_code (void)
+{
+    // No prep code required.
+    return;  // just to have something to pin a breakpoint onto
+}
+
+void destroy_key_call::fill_in_command (void)
+{
+    find_replace_1st ("$handle", handle_str + "_lifetime", call_code);
+    // Figure out what expected results:
+    calc_result_code();
+}
+
+/**********************************************************************************
+   End of methods of class destroy_key_call.
+**********************************************************************************/
+
diff --git a/tools/tf_fuzz/calls/crypto_call.hpp b/tools/tf_fuzz/calls/crypto_call.hpp
new file mode 100644
index 0000000..a35e179
--- /dev/null
+++ b/tools/tf_fuzz/calls/crypto_call.hpp
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef CRYPTO_CALL_HPP
+#define CRYPTO_CALL_HPP
+
+#include <string>
+#include <vector>
+
+/* This project's header files #including other project headers quickly becomes
+   unrealistically complicated.  The only solution is for each .cpp to include
+   the headers it needs.
+#include "psa_call.hpp"
+#include "crypto_asset.hpp"
+*/
+
+
+using namespace std;
+
+class policy_call : public crypto_call
+{
+public:
+    // Data members:  // (low value in hiding these behind setters and getters)
+        string policy_usage;
+        string policy_algorithm;
+    // Methods:
+        policy_call (tf_fuzz_info *test_state, long &asset_ser_no,
+                    asset_search how_asset_found);  // (constructor)
+        ~policy_call (void);
+
+protected:
+    // Data members:
+    // Methods:
+//        void calc_result_code (void);  for *now* keep this in crypto_call::
+
+private:
+    // Data members:
+    // Methods:
+};
+
+
+class key_call : public crypto_call
+{
+public:
+    // Data members:  // (low value in hiding these behind setters and getters)
+        string handle_str;  // the text name of the key's "handle"
+        string key_type;  // DES, AES, RAW, vendor, none, ...
+        string lifetime_str;
+            // similarly, textual representation of the key's lifetime
+        string expected_n_bits;
+           // for get_key_info call (possibly others) exected key size in bits
+    // Methods:
+        key_call (tf_fuzz_info *test_state, long &asset_ser_no,
+                    asset_search how_asset_found);  // (constructor)
+        ~key_call (void);
+
+protected:
+    // Data members:
+    // Methods:
+//        void calc_result_code (void);  for *now* keep this in crypto_call::
+
+private:
+    // Data members:
+    // Methods:
+};
+
+
+class policy_set_call : public policy_call
+{
+public:
+    // Data members:
+    // Methods:
+        void fill_in_prep_code (void);
+        void fill_in_command (void);
+        policy_set_call (tf_fuzz_info *test_state, long &asset_ser_no,
+                         asset_search how_asset_found);  // (constructor)
+        ~policy_set_call (void);
+
+protected:
+    // Data members:
+    // Methods:
+
+private:
+    // Data members:
+    // Methods:
+};
+
+
+class policy_get_call : public policy_call
+{
+public:
+    // Data members:
+    // Methods:
+        void fill_in_prep_code (void);
+        void fill_in_command (void);
+        policy_get_call (tf_fuzz_info *test_state, long &asset_ser_no,
+                         asset_search how_asset_found);  // (constructor)
+        ~policy_get_call (void);
+
+protected:
+    // Data members:
+    // Methods:
+
+private:
+    // Data members:
+    string policy_name;
+    // Methods:
+};
+
+
+class set_key_call : public key_call
+{
+public:
+    // Data members:
+    // Methods:
+        void fill_in_prep_code (void);
+        void fill_in_command (void);
+        set_key_call (tf_fuzz_info *test_state, long &asset_ser_no,
+                         asset_search how_asset_found);  // (constructor)
+        ~set_key_call (void);
+
+protected:
+    // Data members:
+    // Methods:
+
+private:
+    // Data members:
+    // Methods:
+};
+
+
+class get_key_info_call : public key_call
+{
+public:
+    // Data members:
+    // Methods:
+        void fill_in_prep_code (void);
+        void fill_in_command (void);
+        get_key_info_call (tf_fuzz_info *test_state, long &asset_ser_no,
+                           asset_search how_asset_found);  // (constructor)
+        ~get_key_info_call (void);
+
+protected:
+    // Data members:
+    // Methods:
+
+private:
+    // Data members:
+    // Methods:
+};
+
+
+class destroy_key_call : public key_call
+{
+public:
+    // Data members:
+    // Methods:
+        void fill_in_prep_code (void);
+        void fill_in_command (void);
+        destroy_key_call (tf_fuzz_info *test_state, long &asset_ser_no,
+                          asset_search how_asset_found);  // (constructor)
+        ~destroy_key_call (void);
+
+
+protected:
+    // Data members:
+    // Methods:
+
+private:
+    // Data members:
+    // Methods:
+};
+
+#endif  // CRYPTO_CALL_HPP
diff --git a/tools/tf_fuzz/calls/psa_call.cpp b/tools/tf_fuzz/calls/psa_call.cpp
new file mode 100644
index 0000000..51060e1
--- /dev/null
+++ b/tools/tf_fuzz/calls/psa_call.cpp
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#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 "find_or_create_asset.hpp"
+#include "template_line.hpp"
+#include "tf_fuzz.hpp"
+#include "crypto_asset.hpp"
+#include "psa_call.hpp"
+
+
+
+/**********************************************************************************
+   Methods of class psa_call follow:
+**********************************************************************************/
+
+//**************** psa_call methods ****************
+
+psa_call::psa_call (tf_fuzz_info *test_state, long &call_ser_no,   // (constructor)
+                    asset_search how_asset_found)
+{
+    this->test_state = test_state;
+    this->how_asset_found = how_asset_found;
+    set_data.string_specified = false;
+    set_data.set ("");  // actual data
+    assign_data_var.assign ("");  // name of variable assigned (dumped) to
+    assign_data_var_specified = false;
+    set_data.file_specified = false;
+    set_data.file_path.assign ("");
+    this->call_ser_no = call_ser_no = unique_id_counter++;
+    // These will be set in the lower-level constructors, but...
+    prep_code = call_code = check_code = "";
+    print_data = hash_data = false;
+}
+
+psa_call::~psa_call (void)
+{
+    return;  // just to have something to pin a breakpoint onto
+}
+
+void psa_call::write_out_prep_code (ofstream &test_file)
+{
+    test_file << prep_code;
+}
+
+void psa_call::write_out_command (ofstream &test_file)
+{
+    test_file << call_code;
+}
+
+void psa_call::write_out_check_code (ofstream &test_file)
+{
+    if (!expect.pf_nothing) {
+        test_file << check_code;
+    } else {
+        test_file << "    /* (No checks for this PSA call.) */" << endl;
+    }
+}
+
+/**********************************************************************************
+   End of methods of class psa_call.
+**********************************************************************************/
+
+
+/**********************************************************************************
+   Methods of class sst_call follow:
+**********************************************************************************/
+
+/* calc_result_code() fills in the check_code string member with the correct
+   result code (e.g., "PSA_SUCCESS" or whatever).
+
+   This is a big part of where the target modeling -- error modeling -- occurs,
+   so lots of room for further refinement here. */
+void sst_call::calc_result_code (void)
+{
+    if (!expect.pf_nothing) {
+        if (expect.pf_pass) {
+            find_replace_all ("$expect",
+                              test_state->bplate->bplate_string[sst_pass_string],
+                              check_code);
+        } else {
+            if (expect.pf_specified) {
+                find_replace_all ("$expect", expect.pf_result_string,
+                                  check_code);
+            } else {
+                // Figure out what the message should read:
+                switch (how_asset_found) {
+                    case asset_search::found_active:
+                    case asset_search::created_new:
+                        find_replace_all ("$expect",
+                                          test_state->bplate->
+                                              bplate_string[sst_pass_string],
+                                          check_code);
+                        break;
+                    case asset_search::found_deleted:
+                    case asset_search::not_found:
+                        find_replace_all ("$expect",
+                                          test_state->bplate->
+                                              bplate_string[sst_fail_removed],
+                                          check_code);
+                        break;
+                    default:
+                        find_replace_1st ("!=", "==",
+                                          check_code);  // for now, just make sure...
+                        find_replace_all ("$expect",
+                                          test_state->bplate->
+                                              bplate_string[sst_pass_string],
+                                          check_code);  // ... it's *not* PSA_SUCCESS
+                        break;
+                }
+            }
+        }
+    }
+}
+
+sst_call::sst_call (tf_fuzz_info *test_state, long &call_ser_no,   // (constructor)
+                    asset_search how_asset_found)
+                        : psa_call(test_state, call_ser_no, how_asset_found)
+{
+    return;  // just to have something to pin a breakpoint onto
+}
+sst_call::~sst_call (void)
+{
+    return;  // just to have something to pin a breakpoint onto
+}
+
+/**********************************************************************************
+   End of methods of class sst_call.
+**********************************************************************************/
+
+
+/**********************************************************************************
+   Methods of class crypto_call follow:
+**********************************************************************************/
+
+/* calc_result_code() fills in the check_code string member with the correct
+   result code (e.g., "PSA_SUCCESS" or whatever).  This "modeling" needs to be
+   improved and expanded upon *massively* more or less mirroring what is seen in
+   .../test/suites/crypto/crypto_tests_common.c in the psa_key_interface_test()
+   method, (starting around line 20ish). */
+void crypto_call::calc_result_code (void)
+{
+    if (!expect.pf_nothing) {
+        if (expect.pf_pass) {
+            find_replace_1st ("$expect", "PSA_SUCCESS", check_code);
+        } else {
+            if (expect.pf_specified) {
+                find_replace_1st ("$expect", expect.pf_result_string,
+                                  check_code);
+            } else {
+                // Figure out what the message should read:
+                switch (how_asset_found) {
+                    case asset_search::found_active:
+                    case asset_search::created_new:
+                        find_replace_all ("$expect", "PSA_SUCCESS",
+                                          check_code);
+                        break;
+                    case asset_search::found_deleted:
+                        find_replace_all ("$expect", "PSA_ERROR_INVALID_HANDLE",
+                                          check_code);
+                        break;
+                    default:
+                        find_replace_1st ("!=", "==",
+                                          check_code);  // for now, just make sure...
+                        find_replace_all ("$expect", "PSA_SUCCESS",
+                                          check_code);  // ... it's *not* PSA_SUCCESS
+                        break;
+                }
+            }
+        }
+    }
+}
+
+
+crypto_call::crypto_call (tf_fuzz_info *test_state, long &call_ser_no,  // (constructor)
+                          asset_search how_asset_found)
+                             : psa_call(test_state, call_ser_no, how_asset_found)
+{
+    // Nothing further to initialize.
+    return;  // just to have something to pin a breakpoint onto
+}
+crypto_call::~crypto_call (void)
+{
+    // Nothing further to delete.
+    return;  // just to have something to pin a breakpoint onto
+}
+
+/**********************************************************************************
+   End of methods of class crypto_call.
+**********************************************************************************/
+
+
+/**********************************************************************************
+   Methods of class security_call follow:
+**********************************************************************************/
+
+security_call::security_call (tf_fuzz_info *test_state, long &call_ser_no,  // (constructor)
+                          asset_search how_asset_found)
+                             : psa_call(test_state, call_ser_no, how_asset_found)
+{
+    // Nothing further to initialize.
+    return;  // just to have something to pin a breakpoint onto
+}
+security_call::~security_call (void)
+{
+    // Nothing further to delete.
+    return;  // just to have something to pin a breakpoint onto
+}
+
+/* calc_result_code() fills in the check_code string member with the correct result
+   code (e.g., "PSA_SUCCESS" or whatever).
+
+   Since there are no actual PSA calls associated with security calls (so far at least),
+   this should never be invoked. */
+void security_call::calc_result_code (void)
+{
+    // Currently should not be invoked.
+    cerr << "\nError:  Internal:  Please report error #205 to TF-Fuzz developers." << endl;
+    exit (205);
+}
+
+/**********************************************************************************
+   End of methods of class security_call.
+**********************************************************************************/
+
+
diff --git a/tools/tf_fuzz/calls/psa_call.hpp b/tools/tf_fuzz/calls/psa_call.hpp
new file mode 100644
index 0000000..3243810
--- /dev/null
+++ b/tools/tf_fuzz/calls/psa_call.hpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef PSA_CALL_HPP
+#define PSA_CALL_HPP
+
+#include <string>
+
+/* This project's header files #including other project headers quickly becomes
+   unrealistically complicated.  The only solution is for each .cpp to include
+   the headers it needs.
+#include "tf_fuzz.hpp"
+*/
+
+
+using namespace std;
+
+class psa_call
+{
+public:
+    /* Data members -- not all PSA calls have/need these, but they need to be acces-
+       sible polymorphically via a psa_call iterator: */
+        expect_info expect;  // everything about expected results
+        set_data_info set_data;  // everything about setting PSA-asset-data values
+        string assign_data_var;  // name of variable to dump (assign) data into
+        asset_name_id_info asset_id;  // everything about the asset(s) for this line
+        bool assign_data_var_specified;
+        // Expected-result info:
+        bool print_data;  // true to print asset data to test log
+        bool hash_data;  // true to hash data for later comparison
+        string id_string;  // not all PSA calls involve an ID, but a diverse set do
+        long asset_ser_no;  // unique ID for psa asset needed to find data string
+        long call_ser_no;  // unique serial# for this psa_call (see note in tf_fuzz.hpp)
+        asset_search how_asset_found;
+        tf_fuzz_info *test_state;  // the big blob with pointers to everything going on
+        string flags_string;
+            // creation flags, nominally for SST but have to be in a vector of base-class
+    // Methods:
+        virtual void fill_in_prep_code (void) = 0;
+        virtual void fill_in_command (void) = 0;
+        void write_out_prep_code (ofstream &test_file);
+        void write_out_command (ofstream &test_file);
+        void write_out_check_code (ofstream &test_file);
+        psa_call (tf_fuzz_info *test_state, long &asset_ser_no,
+                  asset_search how_asset_found);  // (constructor)
+        ~psa_call (void);
+
+protected:
+    // Data members:
+        string prep_code;  // declarations and such prior to all of the calls
+        string call_code;  // for the call itself
+        string check_code;  // for the code to check success of the call
+        static long unique_id_counter;  // counts off unique IDs for assets
+    // Methods:
+        virtual void calc_result_code (void) = 0;
+
+private:
+    // Data members:
+    // Methods:
+};
+
+
+class sst_call : public psa_call
+{
+public:
+    // Data members:  // (low value in hiding these behind setters and getters)
+    // Methods:
+        sst_call (tf_fuzz_info *test_state, long &asset_ser_no,
+                  asset_search how_asset_found);  // (constructor)
+        ~sst_call (void);
+
+protected:
+    // Data members:
+    // Methods:
+        void calc_result_code (void);
+
+private:
+    // Data members:
+    // Methods:
+};
+
+class crypto_call : public psa_call
+{
+public:
+    // Data members:  // (low value in hiding these behind setters and getters)
+        key_asset the_key_asset;  // are these used (yet)?
+        policy_asset the_policy_asset;
+            // the policy (if any) involved in this call
+    // Methods:
+        crypto_call (tf_fuzz_info *test_state, long &asset_ser_no,
+                    asset_search how_asset_found);  // (constructor)
+        ~crypto_call (void);
+
+protected:
+    // Data members:
+    // Methods:
+        void calc_result_code (void);
+           // for now, the method-overide buck stops here, but that'll probably change
+
+private:
+    // Data members:
+    // Methods:
+};
+
+class security_call : public psa_call
+   /* Strictly speaking, these don't really correspond to PSA calls, so it's a little
+      iffy to subclass them from psa_call.  However, the calling patterns work out
+      right. */
+{
+public:
+    // Data members:  // (low value in hiding these behind setters and getters)
+    // Methods:
+        security_call (tf_fuzz_info *test_state, long &asset_ser_no,
+                       asset_search how_asset_found);  // (constructor)
+        ~security_call (void);
+
+protected:
+    // Data members:
+    // Methods:
+        void calc_result_code (void);
+           // Should never be invoked, since security calls generate no PSA calls.
+
+private:
+    // Data members:
+    // Methods:
+};
+
+#endif  // PSA_CALL_HPP
diff --git a/tools/tf_fuzz/calls/security_call.cpp b/tools/tf_fuzz/calls/security_call.cpp
new file mode 100644
index 0000000..3aeb959
--- /dev/null
+++ b/tools/tf_fuzz/calls/security_call.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <cstdlib>
+
+#include "class_forwards.hpp"
+
+#include "boilerplate.hpp"
+#include "gibberish.hpp"
+#include "compute.hpp"
+#include "randomization.hpp"
+#include "string_ops.hpp"
+#include "data_blocks.hpp"
+#include "psa_asset.hpp"
+#include "find_or_create_asset.hpp"
+#include "template_line.hpp"
+#include "tf_fuzz.hpp"
+#include "crypto_asset.hpp"
+#include "psa_call.hpp"
+#include "security_call.hpp"
+#include "sst_asset.hpp"
+
+
+
+/**********************************************************************************
+   Methods of class hash_call follow:
+**********************************************************************************/
+
+hash_call::hash_call (tf_fuzz_info *test_state,    // (constructor)
+                          long &call_ser_no,
+                          asset_search how_asset_found)
+                             : security_call(test_state, call_ser_no, how_asset_found)
+{
+    // TODO:  Randomize key-policy usage and algorithm:
+}
+hash_call::~hash_call (void)
+{
+    // Nothing further to delete.
+    return;  // just to have something to pin a breakpoint onto
+}
+
+/* Note:  These functions are overridden in all subclasses, but they still need to be
+          defined, or the linker gives the error "undefined reference to `vtable... */
+void hash_call::fill_in_prep_code (void)
+{
+    // No prep code for hash comparisons.
+}
+
+void hash_call::fill_in_command (void)
+{
+    if (asset_id.asset_name_vector.size() > 1) {  // nothing to compare with less than 2
+        // Fill in preceding comment:
+        // Fill in the hash-comparison code itself:
+        for (auto outer = asset_id.asset_name_vector.begin();
+             outer < asset_id.asset_name_vector.end();
+             ++outer) {
+            for (auto inner = outer+1;
+                 inner < asset_id.asset_name_vector.end();
+                 ++inner) {
+                call_code.append ("    if (" + *outer + "_hash == " + *inner + "_hash) {\n");
+                call_code.append (  "        TEST_FAIL(\"Probable data leak between assets "
+                                  + *outer + " and " + *inner + ".\\n\");\n");
+                call_code.append ("        return;\n");
+                call_code.append ("    }\n");
+            }
+        }
+    } else {
+        call_code.assign ("    /* Cannot compare hashes;  only one asset specified. */\n");
+
+    }
+}
+
+/**********************************************************************************
+   End of methods of class hash_call.
+**********************************************************************************/
diff --git a/tools/tf_fuzz/calls/security_call.hpp b/tools/tf_fuzz/calls/security_call.hpp
new file mode 100644
index 0000000..0bc0600
--- /dev/null
+++ b/tools/tf_fuzz/calls/security_call.hpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef SECURITY_CALL_HPP
+#define SECURITY_CALL_HPP
+
+#include <string>
+#include <vector>
+
+/* 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. */
+
+
+using namespace std;
+
+class hash_call : public security_call
+{
+public:
+    // Data members:  // (low value in hiding these behind setters and getters)
+    // Methods:
+        void fill_in_prep_code (void);
+        void fill_in_command (void);
+        /* Hash checks are different from the rest in that there's a single "call" --
+           not a PSA call though -- for all of the assets cited in the template line.
+           In other cases, create a single call for each asset cited by the template
+           line, but in this case it's a single call for all of them. */
+        hash_call (tf_fuzz_info *test_state, long &asset_ser_no,
+                    asset_search how_asset_found);  // (constructor)
+        ~hash_call (void);
+
+protected:
+    // Data members:
+    // Methods:
+//        void calc_result_code (void);  for *now* keep this in security_call::
+
+private:
+    // Data members:
+    // Methods:
+};
+
+#endif // #ifndef SECURITY_CALL_HPP
diff --git a/tools/tf_fuzz/calls/sst_call.cpp b/tools/tf_fuzz/calls/sst_call.cpp
new file mode 100644
index 0000000..93f7a6e
--- /dev/null
+++ b/tools/tf_fuzz/calls/sst_call.cpp
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#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 "find_or_create_asset.hpp"
+#include "template_line.hpp"
+#include "tf_fuzz.hpp"
+#include "crypto_asset.hpp"
+#include "psa_call.hpp"
+#include "sst_call.hpp"
+#include "sst_asset.hpp"
+#include "crypto_asset.hpp"
+
+
+
+/**********************************************************************************
+   Methods of class sst_set_call follow:
+**********************************************************************************/
+
+sst_set_call::sst_set_call (tf_fuzz_info *test_state,    // (constructor)
+                            long &call_ser_no,
+                            asset_search how_asset_found)
+                                : sst_call(test_state, call_ser_no, how_asset_found)
+{
+    // Copy the boilerplate text into local buffers:
+    prep_code.assign ("");  // will fill in, depending upon template line content
+    call_code.assign (test_state->bplate->bplate_string[set_sst_call]);
+    check_code.assign (test_state->bplate->bplate_string[set_sst_check]);
+}
+sst_set_call::~sst_set_call (void)
+{
+    return;  // just to have something to pin a breakpoint onto
+}
+
+void sst_set_call::fill_in_prep_code (void)
+{
+    // Single string of two lines declaring string data and its length:
+    string var_name = asset_id.get_name() + "_data";  // the data holder var
+    prep_code = test_state->bplate->bplate_string[declare_string];
+    find_replace_1st ("$var", var_name, prep_code);
+    find_replace_1st ("$init", set_data.get(), prep_code);
+    var_name = asset_id.get_name() + "_data_size";  // the data length value
+    prep_code.append (test_state->bplate->bplate_string[declare_int]);
+    find_replace_1st ("$var", var_name, prep_code);
+    find_replace_1st ("$init", to_string(set_data.get().length()), prep_code);
+}
+
+void sst_set_call::fill_in_command (void)
+{
+    // Fill in preceding comment:
+    if (how_asset_found == asset_search::created_new) {
+        find_replace_1st ("$op", "Creating", call_code);
+    } else {
+        find_replace_1st ("$op", "Resetting", call_code);
+    }
+    if (asset_id.name_specified) {
+        find_replace_1st ("$description", "\"" + asset_id.get_name() + ",\"",
+                          call_code);
+    } else {
+        find_replace_1st ("$description",
+                          "UID = " + to_string((long) asset_id.id_n), call_code);
+    }
+    if (set_data.string_specified) {
+        find_replace_1st ("$data_source",
+                          "\"" + set_data.get().substr (0, 10) + "...\"",
+                          call_code);
+    } else if (set_data.file_specified) {
+        find_replace_1st ("$data_source", "from file " + set_data.file_path,
+                          call_code);
+    } else {
+        find_replace_1st (" $data_source", "", call_code);
+    }
+    // Fill in the PSA command itself:
+    string var_name = asset_id.get_name() + "_data_size";
+    string id_string = to_string((long) asset_id.id_n);
+    find_replace_1st ("$uid", id_string, call_code);
+    find_replace_1st ("$length", var_name, call_code);
+    var_name = asset_id.get_name() + "_data";
+    find_replace_1st ("$data", var_name, call_code);
+    find_replace_1st ("$flags", flags_string, call_code);
+    // Figure out what expected results:
+    calc_result_code();
+}
+
+/**********************************************************************************
+   End of methods of class sst_set_call.
+**********************************************************************************/
+
+
+/**********************************************************************************
+   Methods of class sst_get_call follow:
+**********************************************************************************/
+
+sst_get_call::sst_get_call (tf_fuzz_info *test_state,    // (constructor)
+                            long &call_ser_no,
+                            asset_search how_asset_found)
+                                 : sst_call(test_state, call_ser_no, how_asset_found)
+{
+    // Copy the boilerplate text into local buffers:
+    prep_code.assign ("");
+    call_code.assign (test_state->bplate->bplate_string[get_sst_call]);
+    check_code.assign ("");
+        // depends upon the particular usage;  will get it in fill_in_command()
+}
+sst_get_call::~sst_get_call (void)
+{
+    return;  // just to have something to pin a breakpoint onto
+}
+
+void sst_get_call::fill_in_prep_code (void)
+{
+    string var_name, temp_string;
+
+    /* Create and use gibberish object to create for-sure-bad data for the
+       psa_ps_get() call to overwrite. */
+    gibberish *gib = new gibberish;
+    char gib_buff[1024];  // TODO:  Sizing of buffers needs to be managed better
+    string wrong_data;
+        /* bogus data to prefill actual data with in order to distinguish
+           whether actual data was provided. */
+
+    gib->sentence (gib_buff, gib_buff + 100 + (rand() % 800));
+        // TODO:  Sizes of random data needs to be strategized better
+    wrong_data = gib_buff;
+    // Expected data:
+    if (expect.data_specified) {
+        /* Template specified expected verbatim, literal data.  Put that into a
+           variable: */
+        var_name.assign (asset_id.get_name() + "_exp_data");
+    } else if (expect.data_var_specified) {
+        // Template specified a variable name for expected data;  use that:
+        var_name.assign (expect.data_var);
+    }
+    // Expected data:
+    if (!(print_data || hash_data)) {
+        prep_code.assign(test_state->bplate->bplate_string[declare_string]);
+        find_replace_1st("$var", var_name, prep_code);
+        find_replace_1st("$init", expect.data, prep_code);
+    }
+    // Actual data:
+    if (assign_data_var_specified) {
+        var_name.assign (assign_data_var);
+    } else {
+        var_name.assign (asset_id.get_name() + "_act_data");
+    }
+    prep_code.append (test_state->bplate->bplate_string[declare_big_string]);
+    find_replace_1st ("$var", var_name, prep_code);
+    find_replace_1st ("$init", wrong_data, prep_code);  // fill with gibberish
+    // (Don't need to specify data length for expected data.)
+    // Actual-data length:
+    var_name = asset_id.get_name() + "_act_length";
+    temp_string.assign (test_state->bplate->bplate_string[declare_int]);
+    find_replace_1st ("static int", "static size_t", temp_string);
+    prep_code.append (temp_string);
+    find_replace_1st ("$var", var_name, prep_code);
+    find_replace_1st ("$init", "0", prep_code);
+    // Offset (always 0 for now):
+    find_replace_1st ("$offset", "0", prep_code);
+    // If hashing the (actual) data, then create a variable for that:
+    if (hash_data) {
+        prep_code.append (test_state->bplate->bplate_string[declare_generic]);
+        var_name.assign (asset_id.get_name() + "_hash");  // where to put the hash of the data
+        find_replace_1st ("$type", "uint32_t", prep_code);
+        find_replace_1st ("$var", var_name, prep_code);
+        find_replace_1st ("$init", "0", prep_code);  // for now...
+    }
+    // Clean-up:
+    delete gib;
+}
+
+void sst_get_call::fill_in_command (void)
+{
+    string exp_var_name, act_var_name, act_data_length, hash_var_name, id_string;
+
+/* TODO:  Flesh-out/fix this (a good try, but not quite right):
+    // Fill in preceding comment:
+    if (how_asset_found == asset_search::created_new) {
+        find_replace_1st ("$op", "Creating", call_code);
+    } else {
+        find_replace_1st ("$op", "Resetting", call_code);
+    }
+    if (asset_id.name_specified) {
+        find_replace_1st ("$description", "\"" + asset_id.get_name() + ",\"",
+                          call_code);
+    } else {
+        find_replace_1st ("$description",
+                          "UID = " + to_string((long) asset_id.id_n), call_code);
+    }
+    if (set_data.string_specified) {
+        find_replace_1st ("$data_source",
+                          "\"" + data.substr (0, 10) + "...\"",
+                          call_code);
+    } else if (set_data.file_specified) {
+        find_replace_1st ("$data_source", "from file " + set_data.file_path,
+                          call_code);
+    } else {
+        find_replace_1st (" $data_source", "", call_code);
+    }
+*/    // Fill in the call itself:
+    if (assign_data_var_specified || print_data || hash_data) {
+        // Dump to variable;  no data-check code needed:
+        check_code.assign (test_state->bplate->bplate_string[get_sst_check]);
+    } else {
+        // Check either against literal or variable, so need data-check code:
+        check_code.assign (test_state->bplate->bplate_string[get_sst_check_all]);
+    }
+    /* Note:  Can fill in the check code identically between the dump-to-variable
+              and check-data cases, because the boilerplate for the former is just an
+              abbreviated version of the latter.  The find_replace_1st() calls for
+              the check-data stuff will just simply not have any effect. */
+    if (expect.data_specified) {
+        exp_var_name.assign (asset_id.get_name() + "_exp_data");
+    } else {
+        // whether expect.data_var_specified is true or not:
+        exp_var_name.assign (expect.data_var);
+    }
+    if (assign_data_var_specified) {
+        act_var_name.assign (assign_data_var);
+    } else {
+        act_var_name.assign (asset_id.get_name() + "_act_data");
+    }
+    /* TODO:  In the case of reading into a variable, does it make more sense to
+       assign into two variables:  Data and length? */
+    act_data_length = asset_id.get_name() + "_act_length";
+
+    id_string = to_string((long) asset_id.id_n);
+    // Fill in the PSA command itself:
+    find_replace_1st ("$uid", id_string, call_code);
+    find_replace_all ("$length", to_string(set_data.get().length()), call_code);
+    find_replace_1st ("$offset", "0", call_code);
+    find_replace_1st ("$exp_data", exp_var_name, call_code);
+    find_replace_all ("$act_data", act_var_name, call_code);
+    find_replace_all ("$act_length", act_data_length, call_code);
+    // Perform most of the same substitutions in the check_code:
+// TODO:  Make data checks contingent upon the PSA call itself passing!
+    find_replace_1st ("$offset", "0", check_code);
+    find_replace_1st ("$exp_data", exp_var_name, check_code);
+    find_replace_all ("$act_data", act_var_name, check_code);
+    find_replace_all ("$length", to_string(expect.data.length()), check_code);
+    if (print_data) {
+        check_code.append (test_state->bplate->bplate_string[test_log]);
+        find_replace_1st ("$message", act_var_name, check_code);
+    }
+    if (hash_data) {
+        hash_var_name.assign (asset_id.get_name() + "_hash");  // where to put the hash of the data
+        check_code.append (test_state->bplate->bplate_string[get_sst_hash]);
+        find_replace_all ("$act_data_var", act_var_name, check_code);
+        find_replace_all ("$hash_var", hash_var_name, check_code);
+    }
+    // Figure out what expected results:
+    calc_result_code();  // this only fills $expect check_code
+    // Fill in expected data, actual data, and length:
+}
+
+/**********************************************************************************
+   End of methods of class sst_get_call.
+**********************************************************************************/
+
+
+/**********************************************************************************
+   Methods of class sst_remove_call follow:
+**********************************************************************************/
+
+sst_remove_call::sst_remove_call (tf_fuzz_info *test_state,    // (constructor)
+                                  long &call_ser_no,
+                                  asset_search how_asset_found)
+                                 : sst_call(test_state, call_ser_no, how_asset_found)
+{
+    // Copy the boilerplate text into local buffers:
+    prep_code.assign ("");
+    call_code.assign (test_state->bplate->bplate_string[remove_sst]);
+    check_code.assign (test_state->bplate->bplate_string[remove_sst_check]);
+}
+sst_remove_call::~sst_remove_call (void)
+{
+    return;  // just to have something to pin a breakpoint onto
+}
+
+void sst_remove_call::fill_in_prep_code (void)
+{
+    // No prep-code.
+    return;  // just to have something to pin a breakpoint onto
+}
+
+void sst_remove_call::fill_in_command (void)
+{
+    // Fill in the call:
+    string id_string = to_string((long) asset_id.id_n);
+    find_replace_1st ("$uid", id_string, call_code);
+    // Fill in expected results:
+    calc_result_code();  // this only fills $expect check_code
+}
+
+/**********************************************************************************
+   End of methods of class sst_remove_call.
+**********************************************************************************/
+
diff --git a/tools/tf_fuzz/calls/sst_call.hpp b/tools/tf_fuzz/calls/sst_call.hpp
new file mode 100644
index 0000000..4557c5c
--- /dev/null
+++ b/tools/tf_fuzz/calls/sst_call.hpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef SST_CALL_HPP
+#define SST_CALL_HPP
+
+#include <string>
+#include <vector>
+#include <cstdint>
+
+/* This project's header files #including other project headers quickly becomes
+   unrealistically complicated.  The only solution is for each .cpp to include
+   the headers it needs.
+#include "sst_asset.hpp"
+#include "psa_call.hpp"
+*/
+
+
+using namespace std;
+
+class sst_set_call : public sst_call
+{
+public:
+    // Data members:
+    // Methods:
+        void fill_in_prep_code (void);
+        void fill_in_command (void);
+        sst_set_call (tf_fuzz_info *test_state, long &asset_ser_no,
+                      asset_search how_asset_found);  // (constructor)
+        ~sst_set_call (void);
+
+protected:
+    // Data members:
+    // Methods:
+
+private:
+    // Data members:
+    // Methods:
+};
+
+
+class sst_get_call : public sst_call
+{
+public:
+    // Data members:
+        uint32_t offset;
+        uint32_t data_length;
+        string data_var_name;
+    // Methods:
+        void fill_in_prep_code (void);
+        void fill_in_command (void);
+        sst_get_call (tf_fuzz_info *test_state, long &asset_ser_no,
+                      asset_search how_asset_found);  // (constructor)
+        ~sst_get_call (void);
+
+protected:
+    // Data members:
+    // Methods:
+
+private:
+    // Data members:
+    // Methods:
+};
+
+class sst_remove_call : public sst_call
+{
+public:
+    // Data members:
+    // Methods:
+        void fill_in_prep_code (void);
+        void fill_in_command (void);
+        sst_remove_call (tf_fuzz_info *test_state, long &asset_ser_no,
+                      asset_search how_asset_found);  // (constructor)
+        ~sst_remove_call (void);
+
+protected:
+    // Data members:
+    // Methods:
+
+private:
+    // Data members:
+    // Methods:
+};
+
+#endif  // SST_CALL_HPP
+
diff --git a/tools/tf_fuzz/class_forwards.hpp b/tools/tf_fuzz/class_forwards.hpp
new file mode 100644
index 0000000..9491811
--- /dev/null
+++ b/tools/tf_fuzz/class_forwards.hpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/* The .hpp files in this project being so self-referential, this file forward-
+   declares all classes before any are attempted to be used. */
+
+#ifndef CLASS_FORWARDS_HPP
+#define CLASS_FORWARDS_HPP
+
+using namespace std;
+
+// data_blocks.hpp:
+class expect_info;
+
+// template_line.hpp:
+class template_line;
+class sst_template_line;
+class key_template_line;
+class policy_template_line;
+
+// sst_template_line.hpp:
+class set_sst_template_line;
+class remove_sst_template_line;
+class read_sst_template_line;
+
+// crypto_template_line.hpp:
+class set_key_template_line;
+class remove_key_template_line;
+class read_key_template_line;
+class set_policy_template_line;
+class read_policy_template_line;
+
+// security.hpp:
+class security;
+class security_hash;
+
+// psa_call.hpp:
+class psa_call;
+
+// sst_call.hpp:
+class sst_call;
+class sst_set_call;
+class sst_get_call;
+class sst_remove_call;
+
+// crypto_call.hpp:
+class crypto_call;
+class policy_set_call;
+class policy_get_call;
+class set_key_call;
+class get_key_info_call;
+class destroy_key_call;
+
+// psa_asset.hpp:
+class psa_asset;
+
+// sst_asset.hpp:
+class sst_asset;
+
+// crypto_asset.hpp:
+class crypto_asset;
+class key_asset;
+class policy_asset;
+class key_asset;
+
+// boilerplate.hpp"
+//enum class boilerplate_texts;  not really a "class," and no need to forward-reference it anyway
+class boilerplate;
+
+// gibberish.hpp:
+class gibberish;
+
+// tf_fuzz.hpp:
+class tf_fuzz_info;
+
+#endif  // #ifndef CLASS_FORWARDS_HPP
diff --git a/tools/tf_fuzz/demo/1 b/tools/tf_fuzz/demo/1
new file mode 100644
index 0000000..7b84f11
--- /dev/null
+++ b/tools/tf_fuzz/demo/1
@@ -0,0 +1,2 @@
+purpose to create an SST asset;
+set sst uid 104 data "Very simple test" expect pass;
diff --git a/tools/tf_fuzz/demo/10 b/tools/tf_fuzz/demo/10
new file mode 100644
index 0000000..3e70099
--- /dev/null
+++ b/tools/tf_fuzz/demo/10
@@ -0,0 +1,2 @@
+purpose to show what happens when you 'read' a non-existent asset;
+read sst name napoleon check "this won't work";
diff --git a/tools/tf_fuzz/demo/11 b/tools/tf_fuzz/demo/11
new file mode 100644
index 0000000..5fdd0fc
--- /dev/null
+++ b/tools/tf_fuzz/demo/11
@@ -0,0 +1,2 @@
+purpose to illustrate that you can override TF-Fuzz's expected result;
+read sst name napoleon check "this won't work" expect pass;
diff --git a/tools/tf_fuzz/demo/12 b/tools/tf_fuzz/demo/12
new file mode 100644
index 0000000..c7825c5
--- /dev/null
+++ b/tools/tf_fuzz/demo/12
@@ -0,0 +1,2 @@
+purpose to more-specifically override TF-Fuzz's expected result;
+read sst name napoleon check "this won't work" expect PSA_ERROR_GENERIC_ERROR;
diff --git a/tools/tf_fuzz/demo/13 b/tools/tf_fuzz/demo/13
new file mode 100644
index 0000000..467ae6d
--- /dev/null
+++ b/tools/tf_fuzz/demo/13
@@ -0,0 +1,4 @@
+purpose to illustrate deleting assets;
+set sst name george data *;
+remove sst name george;
+remove sst name george;
diff --git a/tools/tf_fuzz/demo/14 b/tools/tf_fuzz/demo/14
new file mode 100644
index 0000000..5b9485c
--- /dev/null
+++ b/tools/tf_fuzz/demo/14
@@ -0,0 +1,3 @@
+purpose to remove something that doesn't exist;
+set sst name george data *;
+remove sst name ringo;
diff --git a/tools/tf_fuzz/demo/15 b/tools/tf_fuzz/demo/15
new file mode 100644
index 0000000..613439e
--- /dev/null
+++ b/tools/tf_fuzz/demo/15
@@ -0,0 +1,3 @@
+purpose to show a more-interesting removal case;
+set sst name president george herbert walker bush data "read my lips";
+remove sst *active;  // remove *some* active asset
diff --git a/tools/tf_fuzz/demo/16 b/tools/tf_fuzz/demo/16
new file mode 100644
index 0000000..e7a21b3
--- /dev/null
+++ b/tools/tf_fuzz/demo/16
@@ -0,0 +1,6 @@
+purpose to show a more-interesting removal case;
+set sst name president george herbert walker bush data "no new taxes";
+remove sst *active;  // remove *some* active asset
+remove sst *active;  // remove *some other* active asset
+remove sst *active;  // remove *yet another* active asset
+remove sst *deleted;  // attempt to remove some asset that's already been removed
diff --git a/tools/tf_fuzz/demo/17 b/tools/tf_fuzz/demo/17
new file mode 100644
index 0000000..bdaeece
--- /dev/null
+++ b/tools/tf_fuzz/demo/17
@@ -0,0 +1,8 @@
+purpose to try some more-complex randomization;
+set sst name neil buzz mike data *;
+2 to 5 of {
+    set sst name neil data "that's one small step for [a] man";
+    remove sst *active;
+    set sst name chris kraft data "wear the helmet";
+    remove sst name neil;
+}
diff --git a/tools/tf_fuzz/demo/18 b/tools/tf_fuzz/demo/18
new file mode 100644
index 0000000..f71335e
--- /dev/null
+++ b/tools/tf_fuzz/demo/18
@@ -0,0 +1,9 @@
+purpose to shuffle the deck;
+set sst name Shiva Brahma Vishnu Ganapati data *;
+shuffle {
+    remove sst *active;
+    set sst name Brahma data "I am the creator";
+    set sst name Shiva data "I am the destroyer";
+    set sst name Vishnu data "I am the sustainer";
+    remove sst name Ganapati;
+}
diff --git a/tools/tf_fuzz/demo/19 b/tools/tf_fuzz/demo/19
new file mode 100644
index 0000000..173c45d
--- /dev/null
+++ b/tools/tf_fuzz/demo/19
@@ -0,0 +1,4 @@
+purpose to show the early beginnings of security testing;
+set sst name charles babbage ada lovelace analytic engine alan turing bomb eniac edvac data *;
+read sst name charles babbage ada lovelace analytic engine alan turing bomb eniac edvac hash;
+secure hash neq charles babbage ada lovelace analytic engine alan turing bomb eniac edvac;
diff --git a/tools/tf_fuzz/demo/2 b/tools/tf_fuzz/demo/2
new file mode 100644
index 0000000..9af02c6
--- /dev/null
+++ b/tools/tf_fuzz/demo/2
@@ -0,0 +1,2 @@
+purpose to give assets a human name;
+set sst name forecast data "cloudy with a 20% chance of weather" expect nothing;
diff --git a/tools/tf_fuzz/demo/20 b/tools/tf_fuzz/demo/20
new file mode 100644
index 0000000..6fda99a
--- /dev/null
+++ b/tools/tf_fuzz/demo/20
@@ -0,0 +1,14 @@
+purpose to show that pretty short templates can produce a whole lot of varying test code;
+set sst name charles babbage ada lovelace alan turing bomb eniac edvac data *;
+read sst name charles babbage ada lovelace alan turing bomb eniac edvac hash;
+secure hash neq charles babbage ada lovelace alan turing bomb eniac edvac;
+remove sst *active;
+5 to 10 of {
+    set sst name * data *;
+    remove sst *active;
+    set sst name babbles charage data "I'm confused!";
+    set sst name alace adlove data "wait, something's still not right here...";
+    remove sst name turing;
+    set sst name charles babbage data "that's better";
+    remove sst *deleted;
+}
diff --git a/tools/tf_fuzz/demo/3 b/tools/tf_fuzz/demo/3
new file mode 100644
index 0000000..8f41603
--- /dev/null
+++ b/tools/tf_fuzz/demo/3
@@ -0,0 +1,2 @@
+purpose to show that TF-Fuzz can infer results;
+set sst name john data "Take a holiday in Spain";
diff --git a/tools/tf_fuzz/demo/4 b/tools/tf_fuzz/demo/4
new file mode 100644
index 0000000..912c23a
--- /dev/null
+++ b/tools/tf_fuzz/demo/4
@@ -0,0 +1,2 @@
+purpose to show how to randomize data;
+set sst name gibberish data *;
diff --git a/tools/tf_fuzz/demo/5 b/tools/tf_fuzz/demo/5
new file mode 100644
index 0000000..5290f27
--- /dev/null
+++ b/tools/tf_fuzz/demo/5
@@ -0,0 +1,2 @@
+purpose to show how to randomize name and data;
+set sst name * data *;
diff --git a/tools/tf_fuzz/demo/6 b/tools/tf_fuzz/demo/6
new file mode 100644
index 0000000..2e86d75
--- /dev/null
+++ b/tools/tf_fuzz/demo/6
@@ -0,0 +1,2 @@
+purpose to show a nice party trick;
+set sst name john paul george and ringo data *;
diff --git a/tools/tf_fuzz/demo/7 b/tools/tf_fuzz/demo/7
new file mode 100644
index 0000000..903027e
--- /dev/null
+++ b/tools/tf_fuzz/demo/7
@@ -0,0 +1,2 @@
+purpose same with UIDs;
+set sst uid 17 19 24 31 34 41 data *;
diff --git a/tools/tf_fuzz/demo/8 b/tools/tf_fuzz/demo/8
new file mode 100644
index 0000000..adaacfc
--- /dev/null
+++ b/tools/tf_fuzz/demo/8
@@ -0,0 +1,3 @@
+purpose to create and show an asset;
+set sst name snortwaggle data *;
+read sst name snortwaggle check "almost certainly not *this*";
diff --git a/tools/tf_fuzz/demo/9 b/tools/tf_fuzz/demo/9
new file mode 100644
index 0000000..72cc269
--- /dev/null
+++ b/tools/tf_fuzz/demo/9
@@ -0,0 +1,4 @@
+purpose to dump to a variable or to the log;
+set sst name greebledorf data *;
+read sst name greebledorf check a_variable;
+read sst name greebledorf print;
diff --git a/tools/tf_fuzz/demo/README b/tools/tf_fuzz/demo/README
new file mode 100644
index 0000000..bad7d92
--- /dev/null
+++ b/tools/tf_fuzz/demo/README
@@ -0,0 +1,18 @@
+.../tf_fuzz/demo directory contents:
+
+1  10  11  12  13  14  15  16  17  18  19  2  3  4  5  6  7  8  9  r
+
+--------------------------------------------------------------------------------
+
+The numbered files are test-template files -- input to TF-Fuzz -- for demon-
+strating what it can do.
+
+The "r" shell script is designed to make it quick and easy to run the demo
+tests one by one:  just type "r 5" for example.
+
+The initial, "purpose" line in each numbered file briefly describes what that
+file demonstrates.
+
+--------------
+
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
diff --git a/tools/tf_fuzz/demo/r b/tools/tf_fuzz/demo/r
new file mode 100644
index 0000000..41d0f2a
--- /dev/null
+++ b/tools/tf_fuzz/demo/r
@@ -0,0 +1,18 @@
+#!/usr/bin/bash
+# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+clear
+cat $1
+#sleep 5
+echo
+echo
+echo
+echo
+echo
+echo
+echo --------------------------------------------------
+echo
+echo $ ../tfz -v $1 tossThis2
+../tfz -v $1 tossThis2
diff --git a/tools/tf_fuzz/lib/README b/tools/tf_fuzz/lib/README
new file mode 100644
index 0000000..932e92a
--- /dev/null
+++ b/tools/tf_fuzz/lib/README
@@ -0,0 +1,12 @@
+.../tf_fuzz/lib directory contents:
+
+tfm_boilerplate.txt
+
+--------------------------------------------------------------------------------
+
+This directory contains the customizable "boilerplate" code snippets used to
+write out C source code.
+
+--------------
+
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
diff --git a/tools/tf_fuzz/lib/tfm_boilerplate.txt b/tools/tf_fuzz/lib/tfm_boilerplate.txt
new file mode 100644
index 0000000..3539510
--- /dev/null
+++ b/tools/tf_fuzz/lib/tfm_boilerplate.txt
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+This file is a library text file of boilerplate-text snippets.  TF-Fuzz reads in these
+snippets and then performs targeted text substitutions upon them, to create the indi-
+vidual PSA commands, and other important code snippets.  This one in particular
+library-text file is what might be called the "personality module" for writing tests
+with TF-M syntax.
+
+Four extremely important things about this file:
+*  The individual text snippets are separated by "backtick" (AKA back-apostrophe)
+   characters (see below).  This means that text snippets of TF code can't use backtick
+   characters (reasonably safe for C code).
+*  The text snippets are *positional*.  The loop in boilerplate.cpp reads them in, in
+   the order they appear in this file, into a vector of strings.  The "const int"s in
+   boilerplate.hpp assign symbolic names to the vector indices.  It is therefore
+   *critical* that the, for example, 11th backtick-delineated text snippet in this file,
+   be read into the 11 string in this vector of strings!
+*  This first text snippet that you're now reading -- a README about this file -- is
+   ignored by this boilerplate.cpp loop;  it is not read into this vector of snippets.
+*  To make it easier to track the positional nature of the text snippets in this file,
+   the first three characters, plus the leading \n, of these snippets is trimmed off
+   and ignored.  These first three characters in each string comprise a sequence
+   number, for checking against the "const int" list in boilerplate.hpp.  So, these
+   tags are literally the exactly the 3 characters directly after the backtick termi-
+   nating the previous string.
+
+TO DO:  Hindsight-obvious:  This plus the table of constants in boilerplate.hpp should
+        be replaced with an STL map container!
+`000
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/*
+ * Test purpose:
+ *     $purpose
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "../sst/non_secure/ns_test_helpers.h"
+#include "psa/protected_storage.h"
+#include "test/framework/test_framework_helpers.h"
+#include "crypto_tests_common.h"
+#include "tfm_memory_utils.h"
+`001
+#include <stdint.h>
+
+static uint32_t shift_reg = 0x55555555;
+static int i;  /* generic counter variable */
+
+static void seed_hasher (void)
+{
+    shift_reg = 0x55555555;
+}
+
+static uint32_t lfsr_1b (uint32_t a_bit)
+{
+    int odd;
+    uint32_t polynomial = 0xb4bcd35c;
+
+    odd = ((shift_reg ^ a_bit) & 1) == 1;
+    shift_reg >>= 1;
+    if (odd == 1) {
+        shift_reg ^= polynomial;
+    }
+    if (shift_reg == 0) {
+        /* Should never happen, but... */
+        seed_hasher();
+    }
+    return shift_reg;
+}
+
+static uint32_t crc_byte (uint8_t a_byte)
+{
+    int i;
+    for (i = 0;  i < 8;  i++) {
+        lfsr_1b ((uint32_t) a_byte);
+        a_byte >>= 1;
+    }
+    return shift_reg;
+}
+
+`002
+
+/* This is not yet right for how to run a test;  need to register tests, etc. */
+
+void test_thread (struct test_result_t *ret) {
+    psa_status_t crypto_status;  // result from Crypto calls
+    psa_status_t sst_status;
+
+    /* To prevent unused variable warning, as the variable might not be used
+     * in this testcase
+     */
+    (void)sst_status;
+
+    crypto_status = psa_crypto_init();
+    if (crypto_status != PSA_SUCCESS) {
+        TEST_FAIL("Could not initialize Crypto.");
+        return;
+    }
+
+    TEST_LOG("Test $purpose");
+`003
+    static int $var = $init;
+`004
+    static uint8_t $var[] = "$init";
+`005
+    static uint8_t $var[2048] = "$init";
+`006
+    $type $var = $init;
+`007
+    TEST_LOG($message);
+`008
+    psa_ps_remove($uid);
+`009
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to tear down an SST asset upon test completion.");
+        return;
+    }
+`010
+    psa_destroy_key($handle);
+`011
+    if (crypto_status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to tear down a crypto asset upon test completion");
+        return;
+    }
+`012
+
+    /* Test completed */
+    ret->val = TEST_PASSED;
+}
+`013 PSA_SUCCESS`014 PSA_ERROR_DOES_NOT_EXIST`015
+    /* $op SST asset $description with data $data_source. */
+    sst_status = psa_ps_set($uid, $length, $data,
+                            $flags);
+`016
+    if (sst_status != $expect) {
+        TEST_FAIL("psa_ps_set() expected $expect.");
+        return;
+    }
+`017
+    sst_status = psa_ps_get($uid, $offset, $length, $act_data,
+                            &$act_length);
+`018
+    if (sst_status != $expect) {
+        TEST_FAIL("psa_ps_get() expected $expect.");
+        return;
+    }
+`019
+    if (sst_status != $expect) {
+        TEST_FAIL("psa_ps_get() expected $expect.");
+        return;
+    }
+    /* Check that the data is correct */
+    if (tfm_memcmp($act_data, $exp_data, $length) != 0) {
+        TEST_FAIL("Read data should be equal to result data");
+        return;
+    }
+`020
+    // Hash the actual data for later data-leak checking:
+    seed_hasher();
+    for (i = 0;  i < strlen((char *) $act_data_var);  ++i) {
+        crc_byte ($act_data_var[i]);
+    }
+    $hash_var = shift_reg;
+`021
+    sst_status = psa_ps_remove($uid);
+`022
+    if (sst_status != $expect) {
+        TEST_FAIL("psa_ps_remove() expected $expect.");
+        return;
+    }
+`023
+    crypto_status = psa_key_policy_set_usage(*$policy, $usage, $alg);
+`024
+    if (crypto_status != $expect) {
+        TEST_FAIL("psa_key_policy_set_usage() expected $expect.");
+        return;
+    }
+`025
+    crypto_status = psa_key_policy_get_usage(*$policy);
+`026
+    if (crypto_status != $expect) {
+        TEST_FAIL("psa_key_policy_set_usage() expected $expect.");
+        return;
+    }
+`027
+    crypto_status = psa_create_key($lifetime, *$handle);
+`028
+    if (crypto_status != $expect) {
+        TEST_FAIL("psa_create_key() expected $expect.");
+        return;
+    }
+`029
+    crypto_status = psa_get_key_information($handle, *$type, *$bits);
+`030
+    if (crypto_status != $expect) {
+        TEST_FAIL("psa_get_key_information() expected $expect.");
+        return;
+    }
+`031
+    if ($n_bits != $m_bits) {
+        TEST_FAIL("The number of key bits is different from expected");
+        return;
+    }
+`032
+    crypto_status = psa_destroy_key($handle);
+`033
+    if (crypto_status != $expect) {
+        TEST_FAIL("psa_destroy_key() expected $expect.");
+        return;
+    }
+`
diff --git a/tools/tf_fuzz/parser/README b/tools/tf_fuzz/parser/README
new file mode 100644
index 0000000..f5251a4
--- /dev/null
+++ b/tools/tf_fuzz/parser/README
@@ -0,0 +1,13 @@
+.../tf_fuzz/parser directory contents:
+
+tf_fuzz_grammar.l  tf_fuzz_grammar.y
+
+--------------------------------------------------------------------------------
+
+This directory contains the Lex and YACC grammars for parsing the TF-Fuzz command
+"language," if it can be called that.  The tf_fuzz_grammar.tab.cpp/.hpp files
+generated also form the executive for the entire parsing process.
+
+--------------
+
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
diff --git a/tools/tf_fuzz/parser/tf_fuzz_grammar.l b/tools/tf_fuzz/parser/tf_fuzz_grammar.l
new file mode 100644
index 0000000..d3f1cf6
--- /dev/null
+++ b/tools/tf_fuzz/parser/tf_fuzz_grammar.l
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+
+%{
+#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 "sst_asset.hpp"
+#include "crypto_asset.hpp"
+#include "find_or_create_asset.hpp"
+#include "template_line.hpp"
+#include "tf_fuzz.hpp"
+#include "psa_call.hpp"
+#include "tf_fuzz_grammar.tab.hpp"
+
+int yycolumn = 1;
+
+//char *yytext;
+
+#define YY_USER_ACTION yylloc.first_line = yylloc.last_line = yylineno; \
+    yylloc.first_column = yycolumn; yylloc.last_column = yycolumn + yyleng - 1; \
+    yycolumn += yyleng; \
+    yylval.str = strdup(yytext);
+
+void yyerror (tf_fuzz_info *, const char *str)
+    /* not sure why it sends the yyparse() argument to yyerror(), but OK... */
+{
+    fprintf (stderr, "tf_fuzz template on line %d, at text = \"%s\":  %s\n",
+            yylineno, yytext, str);
+    exit (1);
+}
+
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+%}
+
+%x BLOCK_COMMENT
+
+%option yylineno
+%option nodefault
+%option noyywrap
+%array
+
+%%
+
+\r                        ;   /* ignore all \r */
+\/\/.*\n                  ;   /* ignore C++-style line comments */
+purpose[ \t]+[^;]*;       return PURPOSE;
+"/*"                      {BEGIN(BLOCK_COMMENT);}
+<BLOCK_COMMENT>"*/"       {BEGIN(INITIAL);}
+<BLOCK_COMMENT>\n         ;
+<BLOCK_COMMENT>.          ;
+  /* Root commands: */
+set                       return SET;
+read                      return READ;
+remove                    return REMOVE;
+secure                    return SECURE;
+done                      return DONE;
+  /* PSA-asset types: */
+sst                       return SST;
+key                       return KEY;
+policy                    return POLICY;
+  /* Other root-command operands: */
+expect                    return EXPECT;
+pass                      return PASS;
+nothing                   return NOTHING;
+error                     return ERROR;
+\{                        return OPEN_BRACE;
+\}                        return CLOSE_BRACE;
+;                         return SEMICOLON;
+name                      return NAME;
+uid                       return UID;
+data                      return DATA;
+\*                        return STAR;
+active                    return ACTIVE;
+deleted                   return DELETED;
+check                     return CHECK;
+assign                    return ASSIGN;
+print                     return PRINT;
+hash                      return HASH;
+neq                       return NEQ;
+dfname                    return DFNAME;
+shuffle                   return SHUFFLE;
+to                        return TO;
+of                        return OF;
+  /* Structure operands: */
+[a-zA-z][a-zA-Z_0-9]*     {yylval.str = yytext; return IDENTIFIER_TOK;}
+[+-]?[0-9]*               {yylval.valueN = atol(yytext); return NUMBER_TOK;}
+\'[a-zA-Z_0-9\/\.]+\'     {yylval.str = yytext; return FILE_PATH_TOK;}
+\"[^\"]*\"                {yylval.str = yytext; return LITERAL_TOK;}
+                              /* inside quotes:  anything but a quote, or nothing */
+[ \t\n\r]                 ;   /* ignore white space */
+.                         yyerror ((tf_fuzz_info *) NULL, "Unexpected character");
+
+%%
+
diff --git a/tools/tf_fuzz/parser/tf_fuzz_grammar.y b/tools/tf_fuzz/parser/tf_fuzz_grammar.y
new file mode 100644
index 0000000..600cf53
--- /dev/null
+++ b/tools/tf_fuzz/parser/tf_fuzz_grammar.y
@@ -0,0 +1,1140 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+%{
+#include <iostream>
+#include <vector>
+#include <set>
+
+#include "class_forwards.hpp"
+#include "data_blocks.hpp"
+#include "boilerplate.hpp"
+#include "gibberish.hpp"
+#include "compute.hpp"
+#include "string_ops.hpp"
+#include "psa_asset.hpp"
+#include "find_or_create_asset.hpp"
+#include "template_line.hpp"
+#include "tf_fuzz.hpp"
+#include "sst_asset.hpp"
+#include "crypto_asset.hpp"
+#include "psa_call.hpp"
+#include "crypto_call.hpp"
+#include "sst_call.hpp"
+#include "security_call.hpp"
+#include "secure_template_line.hpp"
+#include "sst_template_line.hpp"
+#include "crypto_template_line.hpp"
+
+/* These items are defined in tf_fuzz_grammar.l.  Note, however that, because
+   of "name mangling," defining them as extern "C" may or may not be ideal,
+   depending upon which compiler -- gcc vs. g++, compiles the output from lex.
+   So far, it seems best without the extern "C", including also compiling
+   under Visual Studio. */
+/* extern "C"
+{ */
+  extern int yylineno;
+  int yywrap() {return 1;}
+  extern char yytext[];
+  extern int yyleng;
+/* } */
+
+int yylex (void);
+void yyerror (tf_fuzz_info *, const char *);
+    /* not sure why it sends the yyparse() argument to yyerror(), but OK... */
+
+/* A few consts just to make code more comprehensible: */
+const bool yes_fill_in_template = true;
+const bool dont_fill_in_template = false;
+const bool yes_create_call = true;
+const bool dont_create_call = false;
+
+tf_fuzz_info *rsrc;
+
+/* These are object pointers used to parse the template and create the test.  Ac-
+   tually, probably only templateLin will be used. */
+template_line                   *templateLin = nullptr;
+  sst_template_line             *sstTemplateLin = nullptr;
+    set_sst_template_line       *setSstTemplateLin = nullptr;
+    read_sst_template_line      *reaSstTemplateLin = nullptr;
+    remove_sst_template_line    *remSstTemplateLin = nullptr;
+  policy_template_line          *polTemplateLin = nullptr;
+    set_policy_template_line    *setPolTemplateLin = nullptr;
+    read_policy_template_line   *reaPolTemplateLin = nullptr;
+  key_template_line             *keyTemplateLin = nullptr;
+    set_key_template_line       *setKeyTemplateLin = nullptr;
+    read_key_template_line      *reaKeyTemplateLin = nullptr;
+    remove_key_template_line    *remKeyTemplateLin = nullptr;
+  security_template_line        *secTemplateLin = nullptr;
+    security_hash_template_line *secHasTemplateLin = nullptr;
+/* Call and asset objects are presumably not immediately needed, because the objects of
+   these types are within the resource object, *rsrc, but even if just to show class
+   hierarchy: */
+psa_call                        *psaCal = nullptr;
+  sst_call                      *sstCal = nullptr;
+    sst_set_call                *sstSetCal = nullptr;
+    sst_get_call                *sstGetCal = nullptr;
+    sst_remove_call             *sstRemCal = nullptr;
+  crypto_call                   *cryCal = nullptr;
+    policy_call                 *polCal = nullptr;
+      policy_set_call           *polSetCal = nullptr;
+      policy_get_call           *polGetCal = nullptr;
+    key_call                    *keyCal = nullptr;
+      get_key_info_call         *getKeyInfCal = nullptr;
+      set_key_call              *makKeyCal = nullptr;
+      destroy_key_call          *desKeyCal = nullptr;
+psa_asset                       *psaAst = nullptr;
+  sst_asset                     *sstAst = nullptr;
+  crypto_asset                  *cryAst = nullptr;
+    policy_asset                *polAst = nullptr;
+    key_asset                   *keyAst = nullptr;
+
+/* For generating random, but readable/memorable, data: */
+gibberish gib;
+char gib_buff[4096];  // spew gibberish into here
+int rand_data_length = 0;
+
+/* General-utility variables: */
+string purp_str;  /* test purpose */
+psa_asset_usage random_asset = psa_asset_usage::all;  /* pick what type of asset at random */
+bool random_name;  /* template didn't specify name, so it's generated randomly */
+string literal_data;  /* literal data for an asset value */
+
+/* Holders for state in read commands: */
+expect_info expect;  /* everything about expected results and data */
+set_data_info set_data;  /* everything about setting the value of PSA-asset data */
+asset_name_id_info asset_id;  /* everything about identifying assets */
+bool assign_data_var_specified;
+string assign_data_var;
+bool print_data;  /* true to just print asset data to the test log */
+bool hash_data;  /* true to just print asset data to the test log */
+
+/* The following are more tied to the template syntax than to the resulting PSA calls */
+string literal;  /* temporary holder for all string literals */
+string identifier;  /* temporary holder for strings representing identifiers */
+string var_name;  /* a variable name */
+string asset_name;  /* as parsed, not yet put into asset_id */
+string aid;  /* string-typed holder for an asset ID in a list thereof */
+int nid;  /* same idea as aid, but for asset ID# lists */
+size_t strFind1, strFind2;  /* for searching through strings */
+
+/* Because of the parsing order, psa_calls of the specific type have to be
+   push_back()ed onto rsrc->calls before their expected results are known.  Therefore,
+   inject those results after parsing the expected results.  add_expect is a vector
+   index of where to start "back-filling" the expect information. */
+unsigned int add_expect = 0;
+
+/* Temporaries: */
+vector<psa_asset*>::iterator t_sst_asset;
+vector<psa_asset*>::iterator t_key_asset;
+vector<psa_asset*>::iterator t_policy_asset;
+sst_call *t_sst_call = nullptr;
+key_call *t_key_call = nullptr;
+policy_call *t_policy_call = nullptr;
+long number;  /* temporary holder for a number, e.g., sting form of UID */
+int i, j, k;
+
+/* Relating to template-statement blocks: */
+vector<template_line*> template_block_vector;  /* (must be *pointers to* templates) */
+vector<int> block_order;  /* "statisticalized" order of template lines in a block */
+int nesting_level = 0;
+    /* how many levels deep in { } nesting currently.  Initially only 0 or 1. */
+bool shuffle_not_pick;
+    /* true to shuffle statements in a block, rather than pick so-and-so
+       number of them at random. */
+int low_nmbr_lines = 1;  /* if picking so-and-so number of template lines from a ... */
+int high_nmbr_lines = 1; /*    ... block at random, these are fewest and most lines. */
+int exact_nmbr_lines = 1;
+
+/* Shortcuts, to reduce code clutter, and reduce risk of coding errors. */
+#define IVM(content) if(rsrc->verbose_mode){content}  /* IVM = "If Verbose Mode" */
+
+using namespace std;
+
+/* randomize_template_lines() chooses a template-line order in cases where they are to
+   be randomized -- shuffled or random picked. */
+void randomize_template_lines (
+    bool shuffle_not_pick,  /* true to perform a shuffle operation rather than pick */
+    int &low_nmbr_lines, /* if picking so-and-so number of template lines from a ... */
+    int &high_nmbr_lines, /*    ... block at random, these are fewest and most lines. */
+    int &exact_nmbr_lines,
+    vector<template_line*> &template_block_vector,
+    vector<int> &block_order
+) {
+    set<int> template_used;  /* used for shuffle */
+    low_nmbr_lines = (low_nmbr_lines < 0)?  0 : low_nmbr_lines;
+    high_nmbr_lines = (high_nmbr_lines < 0)?  0 : high_nmbr_lines;
+    if (low_nmbr_lines > high_nmbr_lines) {
+        int swap = low_nmbr_lines;
+        low_nmbr_lines = high_nmbr_lines;
+        high_nmbr_lines = swap;
+    }
+    template_used.clear();
+    if (shuffle_not_pick) {
+        /* Choose a random order in which to generate all of the
+           template lines in the block: */
+        while (template_used.size() < template_block_vector.size()) {
+            i = rand() % template_block_vector.size();
+            if (template_used.find (i) == template_used.end()) {
+                /* This template not already shuffled in. */
+                block_order.push_back (i);
+                template_used.insert (i);
+            }
+        }
+        /* Done shuffling;  empty out the set: */
+    } else {
+        if (high_nmbr_lines == low_nmbr_lines) {
+            exact_nmbr_lines = low_nmbr_lines;
+                /* just in case the template says "3 to 3 of"... */
+        } else {
+            exact_nmbr_lines =   low_nmbr_lines
+                               + (rand() % (  high_nmbr_lines
+                                            - low_nmbr_lines + 1 )  );
+        }
+        for (int j = 0;  j < exact_nmbr_lines;  ++j) {
+            /* Repeatedly choose a random template line from the block: */
+            i = rand() % template_block_vector.size();
+            block_order.push_back (i);
+        }
+    }
+}
+
+/* interpret_template_line() fills in random data, locates PSA assets, (etc.) and
+   conditionally creates PSA calls for a given template line.  Note that there needs
+   to be a single place where all of this is done, so that statement blocks can be
+   randomized and then dispatched from a single point. */
+void interpret_template_line (
+    template_line *templateLin,  /* the template line to process */
+    tf_fuzz_info *rsrc,  /* program resources in general */
+    set_data_info set_data, psa_asset_usage random_asset,
+    bool assign_data_var_specified, expect_info expect, bool print_data, bool hash_data,
+    string asset_name, string assign_data_var,
+    asset_name_id_info &asset_id,  /* everything about the asset(s) involved */
+    bool create_call_bool,  /* true to create the PSA call at this time */
+    bool create_asset_bool,  /* true to create the PSA asset at this time */
+    bool fill_in_template,  /* true to back-fill info into template */
+    int instance
+        /* if further differentiation to the names or IDs is needed, make this >0 */
+) {
+    const bool yes_fill_in_template = true;  // just to clarify a call
+    vector<psa_asset*> *active_asset, *deleted_asset;
+    vector<psa_asset*>::iterator t_psa_asset;
+
+    if (fill_in_template) {
+        /* Set basic parameters from the template line: */
+        templateLin->asset_id.id_n_not_name = asset_id.id_n_not_name;
+        templateLin->set_data.random_data = set_data.random_data;
+        templateLin->asset_id.set_name (asset_name);
+        /* Fill in state parsed from the template below: */
+        templateLin->assign_data_var_specified = assign_data_var_specified;
+        templateLin->assign_data_var.assign (assign_data_var);
+        templateLin->expect.data_var_specified
+                = expect.data_var_specified;
+        templateLin->expect.data_var.assign (expect.data_var);
+        templateLin->expect.data_specified = expect.data_specified;
+        templateLin->expect.data = expect.data;
+        templateLin->print_data = print_data;
+        templateLin->hash_data = hash_data;
+        templateLin->random_asset = random_asset;
+        templateLin->set_data.string_specified = set_data.literal_data_not_file;
+            /* TODO:  is this right for multiple assets? */
+        if (set_data.literal_data_not_file && !set_data.random_data) {
+            templateLin->set_data.set (literal_data);
+        }
+        /* Save names or IDs to the template-line tracker: */
+        for (auto id_no : asset_id.asset_id_n_vector) {
+             templateLin->asset_id.asset_id_n_vector.push_back (id_no);
+        }
+        asset_id.asset_id_n_vector.clear();
+        for (auto as_name : asset_id.asset_name_vector) {
+             templateLin->asset_id.asset_name_vector.push_back (as_name);
+        }
+        asset_id.asset_name_vector.clear();
+    }
+
+    switch (templateLin->asset_type) {
+        case psa_asset_type::sst:
+            active_asset = &(rsrc->active_sst_asset);
+            deleted_asset = &(rsrc->deleted_sst_asset);
+            /* Currently "invalid" assets aren't used */
+            break;
+        case psa_asset_type::key:
+            active_asset = &(rsrc->active_key_asset);
+            deleted_asset = &(rsrc->deleted_key_asset);
+            break;
+        case psa_asset_type::policy:
+            active_asset = &(rsrc->active_policy_asset);
+            deleted_asset = &(rsrc->deleted_policy_asset);
+            break;
+        default:
+            cerr << "\nError:  Internal:  Please report error "
+                 << "#1502 to TF-Fuzz developers." << endl;
+            exit (1500);
+    }
+
+    if (templateLin->random_asset != psa_asset_usage::all) {
+        /* != psa_asset_usage::all means to choose some known asset at random: */
+        if (templateLin->random_asset == psa_asset_usage::active) {
+            if (active_asset->size() > 0) {
+                i = rand() % active_asset->size();
+                t_psa_asset = active_asset->begin() + i;
+                templateLin->how_asset_found = asset_search::found_active;
+                templateLin->asset_id.id_n = (*t_psa_asset)->asset_id.id_n;
+                templateLin->asset_ser_no = (*t_psa_asset)->asset_ser_no;
+                if (templateLin->is_remove) {
+                    templateLin->set_data.string_specified
+                        = (*t_psa_asset)->set_data.string_specified;
+                    templateLin->asset_id.name_specified
+                        = (*t_psa_asset)->asset_id.name_specified;
+                    templateLin->asset_id.set_calc_name ((*t_psa_asset)->asset_id.get_name());
+                    templateLin->set_data.set_calculated ((*t_psa_asset)->set_data.get());
+                }
+                templateLin->setup_call (set_data, templateLin->set_data.random_data,
+                                         yes_fill_in_template, create_call_bool,
+                                         templateLin, rsrc   );
+                if (templateLin->is_remove) {
+                    /* Move asset from active vector to deleted vector: */
+                    if (templateLin->how_asset_found == asset_search::found_active) {
+                        deleted_asset->push_back(*t_psa_asset);
+                        active_asset->erase(t_psa_asset);
+                    }  /* if not active, deem the call expected to fail. */
+                }
+            } else {
+                cerr << "\nWarning:  Request for random active asset, "
+                     << "when no active assets of that type exist."
+                     << "          Request disregarded." << endl;
+            }
+        } else if (templateLin->random_asset == psa_asset_usage::deleted) {
+            if (deleted_asset->size() > 0) {
+                i = rand() % deleted_asset->size();
+                t_psa_asset = deleted_asset->begin() + i;
+                templateLin->how_asset_found = asset_search::found_deleted;
+                templateLin->asset_id.id_n = (*t_psa_asset)->asset_id.id_n;
+                templateLin->asset_ser_no = (*t_psa_asset)->asset_ser_no;
+                if (templateLin->is_remove) {
+                    templateLin->set_data.string_specified
+                        = (*t_psa_asset)->set_data.string_specified;
+                    templateLin->asset_id.name_specified
+                        = (*t_psa_asset)->asset_id.name_specified;
+                    templateLin->asset_id.set_calc_name (
+                                              (*t_psa_asset)->asset_id.get_name()    );
+                    templateLin->set_data.set_calculated ((*t_psa_asset)->set_data.get());
+                }
+                templateLin->setup_call (set_data, templateLin->set_data.random_data,
+                                         yes_fill_in_template, create_call_bool,
+                                         templateLin, rsrc   );
+                if (templateLin->is_remove && create_call_bool) {
+                    /* Move asset from active vector to deleted vector: */
+                    if (templateLin->how_asset_found == asset_search::found_active) {
+                        deleted_asset->push_back(*t_psa_asset);
+                        active_asset->erase(t_psa_asset);
+                    }  /* if not active, deem the call expected to fail. */
+                }
+            } else {
+                cerr << "\nWarning:  Request for random deleted asset, "
+                     << "when no deleted assets of that type exist."
+                     << "          Request disregarded." << endl;
+            }
+        } /* "invalid" assets are not used, so if not psa_asset_usage::active or
+             psa_asset_usage::deleted, then just ignore the template request */
+    } else {
+        if (asset_id.id_n_not_name) {  /* Not random asset, asset by ID */
+            for (auto id_no :  templateLin->asset_id.asset_id_n_vector) {
+                templateLin->asset_id.set_id_n(id_no);
+                asset_name = templateLin->asset_id.make_id_n_based_name (
+                               id_no + (uint64_t) instance * 10000, asset_name );
+                templateLin->asset_id.set_calc_name (asset_name);
+                templateLin->how_asset_found = rsrc->find_or_create_psa_asset (
+                               templateLin->asset_type, psa_asset_search::id,
+                               psa_asset_usage::all, "",
+                               (id_no + (uint64_t) instance * 10000),
+                               templateLin->asset_ser_no, create_asset_bool,
+                               t_psa_asset );
+                if (!templateLin->is_remove) {
+                    /* Set asset's ID to what's being searched for (whether it's
+                       already that because it's been found, or was just created): */
+                    (*t_psa_asset)->asset_id.id_n = templateLin->asset_id.id_n;
+                    templateLin->expect.data_var = var_name;
+                    if (!set_data.literal_data_not_file) {
+                        templateLin->set_data.set_file (set_data.file_path);
+                    }
+                    if (templateLin->how_asset_found != asset_search::not_found) {
+                        templateLin->asset_id.id_n = (*t_psa_asset)->asset_id.id_n;
+                        templateLin->asset_ser_no = (*t_psa_asset)->asset_ser_no;
+                    }
+                    templateLin->setup_call (set_data, templateLin->set_data.random_data,
+                                             fill_in_template, create_call_bool,
+                                             templateLin, rsrc   );
+                }
+            }
+        } else {  /* Not random asset, asset by name */
+            for (auto as_name :  templateLin->asset_id.asset_name_vector) {
+                /* Also copy into template line object's local vector: */
+                string t_string, t_string2;
+                t_string.assign(as_name);
+                if (instance > 0) {
+                    t_string += "_" + to_string (instance);
+                }
+                templateLin->asset_id.set_name (t_string);
+                templateLin->how_asset_found = rsrc->find_or_create_psa_asset (
+                                templateLin->asset_type, psa_asset_search::name,
+                                psa_asset_usage::all, t_string,
+                                (uint64_t) 0, templateLin->asset_ser_no,
+                                create_asset_bool, t_psa_asset   );
+                if (!templateLin->is_remove) {
+                    /* Give each occurrence a different UID: */
+                    templateLin->asset_id.set_id_n (100 + (rand() % 10000));
+                        /* TODO:  unlikely, but this could alias! */
+                    if (templateLin->how_asset_found != asset_search::not_found) {
+                        templateLin->asset_id.id_n = (*t_psa_asset)->asset_id.id_n;
+                        templateLin->asset_ser_no = (*t_psa_asset)->asset_ser_no;
+                    }
+                    templateLin->setup_call (set_data, templateLin->set_data.random_data,
+                                             yes_fill_in_template, create_call_bool,
+                                             templateLin, rsrc   );
+                }
+            }
+        }
+        if (templateLin->is_remove) {
+            if (templateLin->how_asset_found != asset_search::not_found) {
+                templateLin->asset_ser_no = (*t_psa_asset)->asset_ser_no;
+            }
+            if (templateLin->how_asset_found == asset_search::unsuccessful) {
+                cerr << "\nError:  Tool-internal:  Please report error #109 "
+                     << "to the TF-Fuzz developers." << endl;
+                exit(109);
+            }
+            templateLin->setup_call (set_data, templateLin->set_data.random_data,
+                                     dont_fill_in_template, create_call_bool,
+                                     templateLin, rsrc);
+            templateLin->copy_template_to_asset();
+            /* TODO:  See comment in setup_call() */
+            if (create_call_bool && !templateLin->copy_template_to_call()) {
+                cerr << "\nError:  Tool-internal:  Please report error "
+                     << "#602 to the TF-Fuzz developers." << endl;
+                exit(602);
+            }
+
+            /* TODO:  This ideally would be done in an organized "simulate" stage. */
+            /* Move asset from active vector to deleted vector: */
+            if (   create_call_bool  /* don't do this if just parsing */
+                && templateLin->how_asset_found == asset_search::found_active) {
+                rsrc->deleted_sst_asset.push_back(*t_psa_asset);
+                rsrc->active_sst_asset.erase(t_psa_asset);
+            }  /* if not active, deem the call expected to fail. */
+        }
+    }
+}
+
+%}
+
+%start lines
+
+%union {int valueN; int tokenN; char *str;}
+%token <tokenN> PURPOSE RAW_TEXT
+%token <tokenN> SET READ REMOVE SECURE DONE  /* root commands */
+%token <tokenN> SST KEY POLICY NAME UID STAR ACTIVE DELETED EQUAL DATA DFNAME
+%token <tokenN> CHECK ASSIGN HASH NEQ PRINT EXPECT PASS NOTHING ERROR  /* expected results */
+%token <str> IDENTIFIER_TOK LITERAL_TOK FILE_PATH_TOK  /* variables and content */
+%token <valueN> NUMBER_TOK  /* variables and content */
+%token <tokenN> SEMICOLON SHUFFLE TO OF OPEN_BRACE CLOSE_BRACE  /* block structure */
+
+%define parse.error verbose
+%locations
+%parse-param {tf_fuzz_info *rsrc}
+
+%%
+
+  /* Top-level syntax: */
+lines:      /* nothing */
+      | line lines {
+            IVM(cout << "Lines:  Line number " << yylineno << "." << endl;)
+        }
+      ;
+
+line:
+        PURPOSE {
+            IVM(cout << "Purpose line:  " << flush;)
+            purp_str = yytext;
+            strFind1 = purp_str.find (" ");
+            purp_str = purp_str.substr (strFind1, purp_str.length());
+            purp_str.erase (0, 1);  // (extra space)
+            strFind1 = purp_str.rfind (";");
+            purp_str = purp_str.substr (0, strFind1);
+            rsrc->test_purpose = purp_str;
+            IVM(cout << rsrc->test_purpose << endl;)
+            /* Just a precaution to make sure that these vectors start out empty.
+               Should be, and purpose is typically specified first: */
+            asset_id.asset_id_n_vector.clear();
+            asset_id.asset_name_vector.clear();
+        }
+      | block {
+            /* TODO:  This code may not won't work with "secure hash neq ..." */
+            IVM(cout << "Block of lines." << endl;)
+            /* "Statisticalize" :-) the vector of template lines, then crank
+               the selected lines in order here. */
+            randomize_template_lines (shuffle_not_pick,
+                low_nmbr_lines, high_nmbr_lines, exact_nmbr_lines,
+                template_block_vector, block_order
+            );
+            IVM(cout << "Order of lines in block:  " << flush;
+                 for (auto i : block_order) {
+                     cout << i << "  ";
+                 }
+                 cout << endl;
+            )
+            /* Vector block_order contains the sequence of template lines to be
+               realized, in order.  Pop the indicated template line off the
+               vector and generate code from it: */
+            k = 0;  /* ID adder to at least help ensure uniqueness */
+            for (int i : block_order) {
+                templateLin = template_block_vector[i];
+                /* Note that temLin will have its fields filled in already. */
+                interpret_template_line (
+                    templateLin, rsrc, set_data, random_asset,
+                    assign_data_var_specified, expect, print_data, hash_data,
+                    asset_name, assign_data_var, asset_id,
+                    yes_create_call,  /* did not create call nor asset earlier */
+                    yes_create_asset,
+                    dont_fill_in_template,  /* but did fill it all in before */
+                    k
+                );
+                k++;
+                for (;  add_expect < rsrc->calls.size();  ++add_expect) {
+                    templateLin->expect.copy_expect_to_call (rsrc->calls[add_expect]);
+                }
+            }
+             templateLin->asset_id.asset_id_n_vector.clear();
+             templateLin->asset_id.asset_name_vector.clear();
+            /* Done.  Empty out the "statisticalization" vector: */
+            block_order.clear();
+            /* Empty out the vector of template lines; no longer needed. */
+            template_block_vector.clear();
+            --nesting_level;
+            IVM(cout << "Finished coding block of lines." << endl;)
+        }
+      | command SEMICOLON {
+            IVM(cout << "Command with no expect:  \"" << flush;)
+            if (nesting_level == 0) {  /* if laying down the code now... */
+                for (;  add_expect < rsrc->calls.size();  ++add_expect) {
+                    templateLin->expect.copy_expect_to_call (rsrc->calls[add_expect]);
+                }
+                delete templateLin;  /* done with this template line */
+            } else {
+                /* The template line is now fully decoded, so stuff it onto
+                   vector of lines to be "statisticalized": */
+                template_block_vector.push_back (templateLin);
+            }
+            IVM(cout << yytext << "\"" << endl;)
+        }
+      | command expect SEMICOLON {
+            IVM(cout << "Command with expect:  \"" << flush;)
+            if (nesting_level == 0) {
+                for (;  add_expect < rsrc->calls.size();  ++add_expect) {
+                    templateLin->expect.copy_expect_to_call (rsrc->calls[add_expect]);
+                }
+                delete templateLin;  /* done with this template line */
+            } else {
+                template_block_vector.push_back (templateLin);
+            }
+            IVM(cout << yytext << "\"" << endl;)
+        }
+      ;
+
+command:
+        set_command {
+            IVM(cout << "Set command:  \"" << yytext << "\"" << endl;)
+        }
+      | remove_command {
+            IVM(cout << "Remove command:  \"" << yytext << "\"" << endl;)
+        }
+      | read_command {
+            IVM(cout << "Read command:  \"" << yytext << "\"" << endl;)
+        }
+      | secure_command {
+            IVM(cout << "Security command:  \"" << yytext << "\"" << endl;)
+        }
+      | done_command {
+            IVM(cout << "Done command:  \"" << yytext << "\"" << endl;)
+        }
+      ;
+
+expect:
+        EXPECT PASS  {
+            IVM(cout << "Expect pass clause:  \"" << flush;)
+            templateLin->expect.set_pf_pass();
+            IVM(cout << yytext << "\"" << endl;)
+        }
+      | EXPECT NOTHING {
+            IVM(cout << "Expect nothing clause:  \"" << flush;)
+            templateLin->expect.set_pf_nothing();
+            IVM(cout << yytext << "\"" << endl;)
+        }
+      | EXPECT IDENTIFIER {
+            IVM(cout << "Expect error clause:  \"" << flush;)
+            templateLin->expect.set_pf_error (identifier);
+            IVM(cout << yytext << "\"" << endl;)
+        }
+      ;
+
+  /* Root commands: */
+set_command:
+        SET sst_set_args {
+            IVM(cout << "Set SST command:  \"" << flush;)
+            templateLin = new set_sst_template_line (rsrc);
+            interpret_template_line (
+                templateLin, rsrc, set_data, random_asset,
+                assign_data_var_specified, expect, print_data, hash_data,
+                asset_name, assign_data_var, asset_id,
+                nesting_level == 0 /* create call unless inside {} */,
+                nesting_level == 0 /* similarly, create asset unless inside {} */,
+                yes_fill_in_template, 0
+            );
+            IVM(cout << yytext << "\"" << endl;)
+        }
+      | SET key_set_args {
+            IVM(cout << "Set key command:  \"" << flush;)
+            templateLin = new set_key_template_line (rsrc);
+            interpret_template_line (
+                templateLin, rsrc, set_data, random_asset,
+                assign_data_var_specified, expect, print_data, hash_data,
+                asset_name, assign_data_var, asset_id,
+                nesting_level == 0 /* create call unless inside {} */,
+                nesting_level == 0 /* similarly, create asset unless inside {} */,
+                yes_fill_in_template, 0
+            );
+            IVM(cout << yytext << "\"" << endl;)
+        }
+      | SET policy_set_args {
+            IVM(cout << "Set policy command:  \"" << flush;)
+            templateLin = new set_policy_template_line (rsrc);
+            interpret_template_line (
+                templateLin, rsrc, set_data, random_asset,
+                assign_data_var_specified, expect, print_data, hash_data,
+                asset_name, assign_data_var, asset_id,
+                nesting_level == 0 /* create call unless inside {} */,
+                nesting_level == 0 /* similarly, create asset unless inside {} */,
+                yes_fill_in_template, 0
+            );
+            rsrc->calls.push_back (t_policy_call);
+            IVM(cout << yytext << "\"" << endl;)
+        }
+      ;
+
+remove_command:
+        REMOVE sst_remove_args {
+            IVM(cout << "Remove SST command:  \"" << flush;)
+            templateLin = new remove_sst_template_line (rsrc);
+            interpret_template_line (
+                templateLin, rsrc, set_data, random_asset,
+                assign_data_var_specified, expect, print_data, hash_data,
+                asset_name, assign_data_var, asset_id,
+                nesting_level == 0 /* create call unless inside {} */,
+                dont_create_asset /* don't create an asset being deleted */,
+                yes_fill_in_template, 0
+            );
+            IVM(cout << yytext << "\"" << endl;)
+        }
+      | REMOVE key_remove_args {
+            IVM(cout << "Remove key command:  \"" << flush;)
+            templateLin = new remove_key_template_line (rsrc);
+            templateLin->asset_id.set_name (asset_name);  // set in key_asset_name, below
+            interpret_template_line (
+                templateLin, rsrc, set_data, random_asset,
+                assign_data_var_specified, expect, print_data, hash_data,
+                asset_name, assign_data_var, asset_id,
+                nesting_level == 0 /* create call unless inside {} */,
+                dont_create_asset /* don't create an asset being deleted */,
+                yes_fill_in_template, 0
+            );
+            IVM(cout << yytext << "\"" << endl;)
+        }
+      ;
+
+read_command:
+        READ SST sst_read_args {
+            IVM(cout << "Read SST command:  \"" << flush;)
+            templateLin = new read_sst_template_line (rsrc);
+            interpret_template_line (
+                templateLin, rsrc, set_data, random_asset,
+                assign_data_var_specified, expect, print_data, hash_data,
+                asset_name, assign_data_var, asset_id,
+                nesting_level == 0 /* create call unless inside {} */,
+                dont_create_asset /* if no such asset exists, fail the call */,
+                yes_fill_in_template, 0
+            );
+            IVM(cout << yytext << "\"" << endl;)
+        }
+      | READ KEY key_read_args {
+            IVM(cout << "Read key command:  \"" << flush;)
+            templateLin = new read_key_template_line (rsrc);
+            interpret_template_line (
+                templateLin, rsrc, set_data, random_asset,
+                assign_data_var_specified, expect, print_data, hash_data,
+                asset_name, assign_data_var, asset_id,
+                nesting_level == 0 /* create call unless inside {} */,
+                dont_create_asset /* if no such asset exists, fail the call */,
+                yes_fill_in_template, 0
+            );
+            IVM(cout << yytext << "\"" << endl;)
+        }
+      | READ POLICY policy_read_args {
+            IVM(cout << "Read policy command:  \"" << flush;)
+            templateLin = new read_policy_template_line (rsrc);
+            interpret_template_line (
+                templateLin, rsrc, set_data, random_asset,
+                assign_data_var_specified, expect, print_data, hash_data,
+                asset_name, assign_data_var, asset_id,
+                nesting_level == 0 /* create call unless inside {} */,
+                dont_create_asset /* if no such asset exists, fail the call */,
+                yes_fill_in_template, 0
+            );
+            IVM(cout << yytext << "\"" << endl;)
+        }
+      ;
+
+secure_command: SECURE HASH NEQ ASSET_IDENTIFIER_LIST {
+  /* TODO:  This needs to allow not only SST assets, but mix and match with others
+             (keys especially) as well. */
+            templateLin = new security_hash_template_line (rsrc);
+            templateLin->asset_id.set_name (asset_name);  // set in sst_asset_name, below
+            /* Fill in state parsed out below: */
+            templateLin->assign_data_var_specified = assign_data_var_specified;
+            templateLin->assign_data_var.assign (assign_data_var);
+/* TODO:  Replace the below with templateLin->expect = expect? */
+            templateLin->expect.data_var_specified = expect.data_var_specified;
+            templateLin->expect.data_var.assign (expect.data_var);
+            templateLin->expect.data_specified = expect.data_specified;
+            templateLin->expect.data = literal;
+            templateLin->print_data = print_data;
+            templateLin->hash_data = hash_data;
+            templateLin->random_asset = random_asset;
+            /* Hash checks are different from the rest in that there's a single
+               "call" -- not a PSA call though -- for all of the assets cited in the
+               template line.  In other cases, create a single call for each
+               asset cited by the template line, but not in this case. */
+            for (auto as_name : asset_id.asset_name_vector) {
+                /* Also copy into template line object's local vector: */
+                 templateLin->asset_id.asset_name_vector.push_back (as_name);
+            }
+            /* Don't need to locate the assets, so no searches required. */
+            templateLin->expect.data_var = var_name;
+            templateLin->setup_call (set_data, set_data.random_data, yes_fill_in_template,
+                                     nesting_level == 0, templateLin, rsrc   );
+            asset_id.asset_name_vector.clear();
+            IVM(cout << yytext << "\"" << endl;)
+
+
+        }
+      ;
+
+done_command: DONE {
+            if (nesting_level != 0) {
+                cerr << "\n\"done\" only available at outer-most { } nesting level."
+                     << endl;
+                exit (702);
+            } else {
+                YYACCEPT;
+            }
+        }
+      ;
+
+  /* Root-command parameters: */
+sst_set_args:
+        SST sst_asset_name DATA LITERAL {
+            IVM(cout << "SST-create from literal data:  \"" << flush;)
+            set_data.random_data = false;
+            set_data.literal_data_not_file = true;
+            literal.erase(0,1);    // zap the ""s
+            literal.erase(literal.length()-1,1);
+            literal_data.assign (literal);
+            IVM(cout << yytext << "\"" << endl;)
+        }
+      | SST sst_asset_name DATA STAR {  /* TF-Fuzz supplies random data */
+            IVM(cout << "SST-create from random data" << endl;)
+            set_data.random_data = true;
+            set_data.literal_data_not_file = true;
+            rand_data_length = 40 + (rand() % 256);  /* Note:  Multiple assets do get different data */
+            gib.sentence (gib_buff, gib_buff + rand_data_length - 1);
+            set_data.set (gib_buff);
+            literal.assign (gib_buff);  /* just in case something uses literal */
+        }
+      | SST sst_asset_name DFNAME sst_asset_set_file_path {
+            set_data.literal_data_not_file = set_data.random_data = false;
+            IVM(cout << "SST-create from file:  " << yytext << "\"" << endl;)
+            /* TODO:  Need to decide whether the concept of using files to set SST
+                       asset values has meaning, and then write code to write code to
+                       set data appropriately from the file. */
+        }
+      ;
+
+sst_read_args:
+        sst_asset_name ASSIGN IDENTIFIER {  /* dump to variable */
+            IVM(cout << "SST-read dump to variable:  \"" << flush;)
+            /* TODO:  set_data content probably doesn't need to be set here;
+                       constructor probably sets it fine. */
+            set_data.random_data = false;
+            set_data.literal_data_not_file = true;
+            assign_data_var.assign (identifier);
+            assign_data_var_specified = true;
+            expect.data_specified = false;
+            expect.data_var_specified = false;
+            IVM(cout << yytext << "\"" << endl;)
+        }
+      | sst_asset_name CHECK sst_read_args_var_name {  /* check against variable */
+            IVM(cout << "SST-read check against variable:  \""
+                     << yytext << "\"" << endl;)
+            /* TODO:  set_data content probably doesn't need to be set here;
+                       constructor probably sets it fine. */
+            set_data.random_data = false;
+            set_data.literal_data_not_file = true;  /* most importantly not file */
+            set_data.set (literal);
+            assign_data_var_specified = false;
+            expect.data_specified = false;
+            expect.data_var_specified = true;
+            expect.data_var = identifier;
+        }
+      | sst_asset_name CHECK LITERAL {  /* check against literal */
+            IVM(cout << "SST-read check against literal:  " << flush;)
+            /* TODO:  set_data content probably doesn't need to be set here;
+                       constructor probably sets it fine. */
+            set_data.random_data = false;
+            set_data.literal_data_not_file = true;
+            expect.data.assign (literal);
+            expect.data.erase(0,1);    // zap the ""s
+            expect.data.erase(expect.data.length()-1,1);
+            assign_data_var_specified = false;
+            expect.data_specified = true;
+            expect.data_var_specified = false;
+            IVM(cout << yytext << endl;)
+        }
+      | sst_asset_name PRINT {  /* print out content in test log */
+            IVM(cout << "SST-read log to test log:  \"" << flush;)
+            /* TODO:  set_data content probably doesn't need to be set here;
+                       constructor probably sets it fine. */
+            set_data.random_data = false;
+            set_data.literal_data_not_file = true;
+            assign_data_var_specified = false;
+            expect.data_specified = false;
+            expect.data_var_specified = false;
+            print_data = true;
+            IVM(cout << yytext << "\"" << endl;)
+        }
+      | sst_asset_name HASH {  /* hash the data and save for later comparison */
+            IVM(cout << "SST-read hash for future data-leak detection:  \"" << flush;)
+            /* TODO:  set_data content probably doesn't need to be set here;
+                       constructor probably sets it fine. */
+            set_data.random_data = false;
+            set_data.literal_data_not_file = true;
+            assign_data_var_specified = false;
+            expect.data_specified = false;
+            expect.data_var_specified = false;
+            hash_data = true;
+            rsrc->include_hashing_code = true;
+            IVM(cout << yytext << "\"" << endl;)
+        }
+      | sst_asset_name DFNAME sst_asset_dump_file_path {  /* dump to file */
+            IVM(cout << "SST-read dump to file:  \""
+                     << yytext << "\"" << endl;)
+            set_data.literal_data_not_file = set_data.random_data = false;
+        }
+      ;
+
+sst_remove_args:
+      SST sst_asset_name {
+            IVM(cout << "SST-remove arguments:  \""
+                     << yytext << "\"" << endl;)
+      }
+      ;
+
+sst_asset_name:
+        NAME ASSET_IDENTIFIER_LIST {
+            IVM(cout << "SST-asset identifier list:  \"" << flush;)
+            random_name = false;
+            asset_name.assign (identifier);  /* TODO:  Not sure this ultimately has any effect... */
+            random_asset = psa_asset_usage::all;  /* don't use random asset */
+            asset_id.id_n_not_name = false;
+            IVM(cout << yytext << "\"" << endl;)
+        }
+      | NAME STAR {
+            IVM(cout << "SST-asset random identifier:  \"" << flush;)
+            random_name = true;
+            rand_data_length = 2 + (rand() % 10);
+            gib.word (false, gib_buff, gib_buff + rand_data_length - 1);
+            aid.assign (gib_buff);
+            asset_id.asset_name_vector.push_back (aid);
+            random_asset = psa_asset_usage::all;  /* don't use random asset */
+            asset_id.id_n_not_name = false;
+            IVM(cout << yytext << "\"" << endl;)
+        }
+      | UID ASSET_NUMBER_LIST {
+            IVM(cout << "SST-asset UID list:  \"" << flush;)
+            random_name = false;
+            random_asset = psa_asset_usage::all;  /* don't use random asset */
+            asset_id.id_n_not_name = true;
+            asset_id.id_n_specified = true;
+            IVM(cout << yytext << "\"" << endl;)
+        }
+      | UID STAR {
+            IVM(cout << "SST-asset random UID:  \"" << flush;)
+            asset_id.id_n_not_name = true;
+            random_name = false;
+            nid = 100 + (rand() % 10000);
+            asset_id.asset_id_n_vector.push_back (nid);
+            random_asset = psa_asset_usage::all;  /* don't use random asset */
+            IVM(cout << yytext << "\"" << endl;)
+        }
+      | STAR ACTIVE {
+            IVM(cout << "SST-asset random active:  \"" << flush;)
+            random_asset = psa_asset_usage::active;
+            asset_id.id_n_not_name = false;
+            IVM(cout << yytext << "\"" << endl;)
+        }
+      | STAR DELETED {
+            IVM(cout << "SST-asset random deleted:  \"" << flush;)
+            random_asset = psa_asset_usage::deleted;
+            asset_id.id_n_not_name = false;
+            IVM(cout << yytext << "\"" << endl;)
+        }
+      ;
+
+sst_asset_set_file_path:
+      FILE_PATH {
+            IVM(cout << "SST-asset-create file path:  \"" << flush;)
+            IVM(cout << yytext << "\"" << endl;)
+      }
+      ;
+
+sst_read_args_var_name:
+      IDENTIFIER {
+            IVM(cout << "SST-read-arguments variable name:  \"" << flush;)
+            var_name = yytext;
+            IVM(cout << yytext << "\"" << endl;)
+      }
+      ;
+
+sst_asset_dump_file_path:
+      FILE_PATH {
+            IVM(cout << "SST-asset dump-file path:  \"" << flush;)
+            set_data.file_path = yytext;
+            IVM(cout << yytext << "\"" << endl;)
+      }
+      ;
+
+key_set_args:
+      KEY key_id POLICY policy_asset_name {
+            IVM(cout << "Key-create arguments:  \""
+                     << yytext << "\"" << endl;)
+      }
+      ;
+
+key_remove_args:
+      KEY key_id {
+            IVM(cout << "Key-remove arguments:  \""
+                     << yytext << "\"" << endl;)
+      }
+      ;
+
+key_read_args:
+      KEY key_id key_read_var_name {
+            IVM(cout << "Key dump to variable:  \""
+                     << yytext << "\"" << endl;)
+      }
+      ;
+
+key_read_var_name:
+      IDENTIFIER {
+            IVM(cout << "Key-read variable name:  \""
+                     << yytext << "\"" << endl;)
+      }
+      ;
+
+key_id:
+      IDENTIFIER {
+            IVM(cout << "Key ID:  \""
+                     << yytext << "\"" << endl;)
+      }
+      ;
+
+policy_set_args:
+      POLICY policy_asset_name {
+            IVM(cout << "Policy-create arguments:  \""
+                     << yytext << "\"" << endl;)
+      }
+      ;
+
+policy_read_args:
+      POLICY policy_asset_name policy_read_var_name {
+            IVM(cout << "Policy dump to variable:  \""
+                     << yytext << "\"" << endl;)
+      }
+      ;
+
+policy_asset_name:
+      IDENTIFIER {
+            IVM(cout << "Policy Asset ID:  \"" << flush;)
+            asset_name = identifier;
+            IVM(cout << yytext << "\"" << endl;)
+      }
+      ;
+
+policy_read_var_name:
+      IDENTIFIER {
+            IVM(cout << "Policy read variable name:  \""
+                     << yytext << "\"" << endl;)
+      }
+      ;
+
+/* Code structuring: */
+block:
+        SHUFFLE block_content {
+            IVM(cout << "Shuffled block:  \"" << flush;)
+            if (nesting_level > 1) {
+                cerr << "\nError:  Sorry, currently only one level of { } "
+                     << "nesting is allowed." << endl;
+                exit (500);
+            }
+            shuffle_not_pick = true;
+            low_nmbr_lines = high_nmbr_lines = 0;  /* not used, but... */
+            IVM(cout << yytext << "\"" << endl;)
+        }
+      | exact_sel_count OF block_content {
+            IVM(cout << "Fixed number of lines from block:  \"" << flush;)
+            shuffle_not_pick = false;
+            /* low_nmbr_lines and high_nmbr_lines are set below. */
+            IVM(cout << yytext << "\"" << endl;)
+        }
+      | low_sel_count TO high_sel_count OF block_content {
+            IVM(cout << "Range number of lines from block:  \"" << flush;)
+            if (nesting_level > 1) {
+                cerr << "\nError:  Sorry, currently only one level of { } "
+                     << "nesting is allowed." << endl;
+                exit (502);
+            }
+            shuffle_not_pick = false;
+            /* low_nmbr_lines and high_nmbr_lines are set below. */
+            IVM(cout << yytext << "\"" << endl;)
+        }
+      ;
+
+block_content:
+        open_brace lines close_brace {
+            IVM(cout << "Block content:  \"" << yytext << "\"" << endl;)
+        }
+      | line {
+            IVM(cout << "Single-line would-be-block content:  \"" << flush;)
+            IVM(cout << yytext << "\"" << endl;)
+        }
+      ;
+
+open_brace:   OPEN_BRACE {
+            IVM(cout << "Open brace:  \"" << flush;)
+            template_block_vector.clear();  // clean slate of template lines
+            nesting_level = 1;
+            IVM(cout << yytext << "\"" << endl;)
+      }
+      ;
+
+close_brace:  CLOSE_BRACE {
+            IVM(cout << "Close brace:  " << flush;)
+            IVM(cout << yytext << "\"" << endl;)
+      }
+      ;
+
+  /* Low-level structures: */
+
+  /* Please see comment before ASSET_IDENTIFIER_LIST, below. */
+ASSET_NUMBER_LIST:    ASSET_NUMBER ASSET_NUMBERS;  /* at least one number */
+
+ASSET_NUMBERS:      /* nothing, or */
+      | ASSET_NUMBER ASSET_NUMBERS;
+
+ASSET_NUMBER:     NUMBER_TOK {
+            IVM(cout << "ASSET_NUMBER:  \"" << flush;)
+            nid = atol(yytext);
+            asset_id.asset_id_n_vector.push_back (nid);
+            IVM(cout << yytext << "\"" << endl;)
+      }
+      ;
+
+  /* ASSET_IDENTIFIER* are used specifically for lists of assets in a template line.
+     That, as opposed to list of identifers in general.  The difference is the need
+     to queue ASSET_IDENTIFIERS up into asset_id.asset_name_vector, and have to do so
+     here before they "vanish." */
+ASSET_IDENTIFIER_LIST:  ASSET_IDENTIFIER ASSET_IDENTIFIERS;  /* (at least one) */
+
+ASSET_IDENTIFIERS:
+        /* nothing, or */
+      | ASSET_IDENTIFIER ASSET_IDENTIFIERS;
+
+ASSET_IDENTIFIER: IDENTIFIER_TOK {
+            IVM(cout << "ASSET_IDENTIFIER:  \"" << flush;)
+            aid = identifier = yytext;
+            asset_id.asset_name_vector.push_back (aid);
+            IVM(cout << yytext << "\"" << endl;)
+      }
+      ;
+
+IDENTIFIER: IDENTIFIER_TOK {
+            IVM(cout << "IDENTIFIER:  \"" << flush;)
+            identifier = yytext;
+            IVM(cout << yytext << "\"" << endl;)
+      }
+      ;
+
+FILE_PATH: FILE_PATH_TOK {
+            IVM(cout << "FILE_PATH:  \"" << flush;)
+            set_data.file_path = yytext;
+            IVM(cout << yytext << "\"" << endl;)
+      }
+      ;
+
+  /* These are related to randomized blocks of template lines: */
+
+exact_sel_count:  NUMBER {
+            IVM(cout << "Exact number of random template lines:  \"" << flush;)
+            low_nmbr_lines = high_nmbr_lines = exact_nmbr_lines = number;
+            ++nesting_level;
+            IVM(cout << number << "\"" << endl;)
+      }
+      ;
+
+low_sel_count:  NUMBER {
+            IVM(cout << "Least number of random template lines:  \"" << flush;)
+            low_nmbr_lines = number;
+            IVM(cout << number << "\"" << endl;)
+      }
+      ;
+
+high_sel_count:  NUMBER {
+            IVM(cout << "Most number of random template lines:  \"" << flush;)
+            high_nmbr_lines = number;
+            ++nesting_level;
+            IVM(cout << number << "\"" << endl;)
+      }
+      ;
+
+
+  /* These are general-case numbers, literals and such: */
+
+NUMBER:   NUMBER_TOK {
+            IVM(cout << "NUMBER:  \"" << flush;)
+            number = atol(yytext);
+            IVM(cout << yytext << "\"" << endl;)
+      }
+      ;
+
+LITERAL:  LITERAL_TOK {
+            IVM(cout << "LITERAL:  " << flush;)
+            literal = yytext;
+            IVM(cout << yytext << endl;)
+      }
+      ;
+
+
+%%
+
diff --git a/tools/tf_fuzz/regression/000001_set_sst_uid_data_expect_pass/check.py b/tools/tf_fuzz/regression/000001_set_sst_uid_data_expect_pass/check.py
new file mode 100644
index 0000000..a215e77
--- /dev/null
+++ b/tools/tf_fuzz/regression/000001_set_sst_uid_data_expect_pass/check.py
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+import sys, os
+
+def main():
+    if len(sys.argv) != 4:
+        print >> sys.stderr, "%s requires 3 command-line arguments. Exiting." % sys.argv[0]
+        sys.exit(1)
+
+    #print "Command line args: %s" % (', '.join(sys.argv[1:4]))
+    sys.exit(0)
+
+if __name__ == "__main__":
+    main()
diff --git a/tools/tf_fuzz/regression/000001_set_sst_uid_data_expect_pass/exp_stdout_stderr b/tools/tf_fuzz/regression/000001_set_sst_uid_data_expect_pass/exp_stdout_stderr
new file mode 100644
index 0000000..05de8db
--- /dev/null
+++ b/tools/tf_fuzz/regression/000001_set_sst_uid_data_expect_pass/exp_stdout_stderr
@@ -0,0 +1,19 @@
+Trusted Firmware Fuzzer (TF-Fuzz) starting...
+
+Info:  random seed was not specified.
+
+Using seed value of \d+ \(0x[a-f\d]+\).
+Purpose line:  to create an SST asset
+ASSET_NUMBER:  "104"
+SST-asset UID list:  "data"
+LITERAL:  "Very simple test"
+SST-create from literal data:  ""Very simple test""
+Set SST command:  ""Very simple test""
+Set command:  ""Very simple test""
+Expect pass clause:  "pass"
+Command with expect:  ";"
+Lines:  Line number 3.
+Lines:  Line number 3.
+Writing test file, test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tools/tf_fuzz/regression/000001_set_sst_uid_data_expect_pass/exp_test.c b/tools/tf_fuzz/regression/000001_set_sst_uid_data_expect_pass/exp_test.c
new file mode 100644
index 0000000..1573156
--- /dev/null
+++ b/tools/tf_fuzz/regression/000001_set_sst_uid_data_expect_pass/exp_test.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/*
+ * Test purpose:
+ *     to create an SST asset
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "../sst/non_secure/ns_test_helpers.h"
+#include "psa/protected_storage.h"
+#include "test/framework/test_framework_helpers.h"
+#include "crypto_tests_common.h"
+#include "tfm_memory_utils.h"
+
+/* This is not yet right for how to run a test;  need to register tests, etc. */
+
+void test_thread (struct test_result_t *ret) {
+    psa_status_t crypto_status;  // result from Crypto calls
+    psa_status_t sst_status;
+
+    /* To prevent unused variable warning, as the variable might not be used
+     * in this testcase
+     */
+    (void)sst_status;
+
+    crypto_status = psa_crypto_init();
+    if (crypto_status != PSA_SUCCESS) {
+        TEST_FAIL("Could not initialize Crypto.");
+        return;
+    }
+
+    TEST_LOG("Test to create an SST asset");
+
+
+    /* Variables (etc.) to initialize and check PSA assets: */
+    static uint8_t SST_ID_104_data[] = "Very simple test";
+    static int SST_ID_104_data_size = 16;
+
+
+    /* PSA calls to test: */
+
+    /* Creating SST asset UID = 104 with data "Very simpl...". */
+    sst_status = psa_ps_set(104, SST_ID_104_data_size, SST_ID_104_data,
+                            PSA_STORAGE_FLAG_********);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+        return;
+    }
+
+
+    /* Removing assets left over from testing: */
+    psa_ps_remove(104);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to tear down an SST asset upon test completion.");
+        return;
+    }
+
+    /* Test completed */
+    ret->val = TEST_PASSED;
+}
diff --git a/tools/tf_fuzz/regression/000001_set_sst_uid_data_expect_pass/template b/tools/tf_fuzz/regression/000001_set_sst_uid_data_expect_pass/template
new file mode 100644
index 0000000..7b84f11
--- /dev/null
+++ b/tools/tf_fuzz/regression/000001_set_sst_uid_data_expect_pass/template
@@ -0,0 +1,2 @@
+purpose to create an SST asset;
+set sst uid 104 data "Very simple test" expect pass;
diff --git a/tools/tf_fuzz/regression/000002_set_sst_name_data_expect_nothing/check.py b/tools/tf_fuzz/regression/000002_set_sst_name_data_expect_nothing/check.py
new file mode 100644
index 0000000..a215e77
--- /dev/null
+++ b/tools/tf_fuzz/regression/000002_set_sst_name_data_expect_nothing/check.py
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+import sys, os
+
+def main():
+    if len(sys.argv) != 4:
+        print >> sys.stderr, "%s requires 3 command-line arguments. Exiting." % sys.argv[0]
+        sys.exit(1)
+
+    #print "Command line args: %s" % (', '.join(sys.argv[1:4]))
+    sys.exit(0)
+
+if __name__ == "__main__":
+    main()
diff --git a/tools/tf_fuzz/regression/000002_set_sst_name_data_expect_nothing/exp_stdout_stderr b/tools/tf_fuzz/regression/000002_set_sst_name_data_expect_nothing/exp_stdout_stderr
new file mode 100644
index 0000000..da7e757
--- /dev/null
+++ b/tools/tf_fuzz/regression/000002_set_sst_name_data_expect_nothing/exp_stdout_stderr
@@ -0,0 +1,19 @@
+Trusted Firmware Fuzzer (TF-Fuzz) starting...
+
+Info:  random seed was not specified.
+
+Using seed value of \d+ \(0x[a-f\d]+\).
+Purpose line:  to give assets a human name
+ASSET_IDENTIFIER:  "forecast"
+SST-asset identifier list:  "data"
+LITERAL:  "sunny with a 30% chance of weather!"
+SST-create from literal data:  ""sunny with a 30% chance of weather!""
+Set SST command:  ""sunny with a 30% chance of weather!""
+Set command:  ""sunny with a 30% chance of weather!""
+Expect nothing clause:  "nothing"
+Command with expect:  ";"
+Lines:  Line number 3.
+Lines:  Line number 3.
+Writing test file, test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tools/tf_fuzz/regression/000002_set_sst_name_data_expect_nothing/exp_test.c b/tools/tf_fuzz/regression/000002_set_sst_name_data_expect_nothing/exp_test.c
new file mode 100644
index 0000000..c382d9b
--- /dev/null
+++ b/tools/tf_fuzz/regression/000002_set_sst_name_data_expect_nothing/exp_test.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/*
+ * Test purpose:
+ *     to give assets a human name
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "../sst/non_secure/ns_test_helpers.h"
+#include "psa/protected_storage.h"
+#include "test/framework/test_framework_helpers.h"
+#include "crypto_tests_common.h"
+#include "tfm_memory_utils.h"
+
+/* This is not yet right for how to run a test;  need to register tests, etc. */
+
+void test_thread (struct test_result_t *ret) {
+    psa_status_t crypto_status;  // result from Crypto calls
+    psa_status_t sst_status;
+
+    /* To prevent unused variable warning, as the variable might not be used
+     * in this testcase
+     */
+    (void)sst_status;
+
+    crypto_status = psa_crypto_init();
+    if (crypto_status != PSA_SUCCESS) {
+        TEST_FAIL("Could not initialize Crypto.");
+        return;
+    }
+
+    TEST_LOG("Test to give assets a human name");
+
+
+    /* Variables (etc.) to initialize and check PSA assets: */
+    static uint8_t forecast_data[] = "sunny with a 30% chance of weather!";
+    static int forecast_data_size = 35;
+
+
+    /* PSA calls to test: */
+
+    /* Creating SST asset "forecast," with data "sunny with...". */
+    sst_status = psa_ps_set(@@@001@@@, forecast_data_size, forecast_data,
+                            PSA_STORAGE_FLAG_********);
+    /* (No checks for this PSA call.) */
+
+
+    /* Removing assets left over from testing: */
+    psa_ps_remove(@@@001@@@);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to tear down an SST asset upon test completion.");
+        return;
+    }
+
+    /* Test completed */
+    ret->val = TEST_PASSED;
+}
diff --git a/tools/tf_fuzz/regression/000002_set_sst_name_data_expect_nothing/template b/tools/tf_fuzz/regression/000002_set_sst_name_data_expect_nothing/template
new file mode 100644
index 0000000..7292031
--- /dev/null
+++ b/tools/tf_fuzz/regression/000002_set_sst_name_data_expect_nothing/template
@@ -0,0 +1,2 @@
+purpose to give assets a human name;
+set sst name forecast data "sunny with a 30% chance of weather!" expect nothing;
diff --git a/tools/tf_fuzz/regression/000003_set_sst_name_data/check.py b/tools/tf_fuzz/regression/000003_set_sst_name_data/check.py
new file mode 100644
index 0000000..a215e77
--- /dev/null
+++ b/tools/tf_fuzz/regression/000003_set_sst_name_data/check.py
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+import sys, os
+
+def main():
+    if len(sys.argv) != 4:
+        print >> sys.stderr, "%s requires 3 command-line arguments. Exiting." % sys.argv[0]
+        sys.exit(1)
+
+    #print "Command line args: %s" % (', '.join(sys.argv[1:4]))
+    sys.exit(0)
+
+if __name__ == "__main__":
+    main()
diff --git a/tools/tf_fuzz/regression/000003_set_sst_name_data/exp_stdout_stderr b/tools/tf_fuzz/regression/000003_set_sst_name_data/exp_stdout_stderr
new file mode 100644
index 0000000..1dbe62d
--- /dev/null
+++ b/tools/tf_fuzz/regression/000003_set_sst_name_data/exp_stdout_stderr
@@ -0,0 +1,18 @@
+Trusted Firmware Fuzzer (TF-Fuzz) starting...
+
+Info:  random seed was not specified.
+
+Using seed value of \d+ \(0x[a-f\d]+\).
+Purpose line:  to show that TF-Fuzz can infer results
+ASSET_IDENTIFIER:  "jonathan"
+SST-asset identifier list:  "data"
+LITERAL:  "I am the man"
+SST-create from literal data:  ""I am the man""
+Set SST command:  ""I am the man""
+Set command:  ""I am the man""
+Command with no expect:  ";"
+Lines:  Line number 3.
+Lines:  Line number 3.
+Writing test file, test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tools/tf_fuzz/regression/000003_set_sst_name_data/exp_test.c b/tools/tf_fuzz/regression/000003_set_sst_name_data/exp_test.c
new file mode 100644
index 0000000..ea88a13
--- /dev/null
+++ b/tools/tf_fuzz/regression/000003_set_sst_name_data/exp_test.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/*
+ * Test purpose:
+ *     to show that TF-Fuzz can infer results
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "../sst/non_secure/ns_test_helpers.h"
+#include "psa/protected_storage.h"
+#include "test/framework/test_framework_helpers.h"
+#include "crypto_tests_common.h"
+#include "tfm_memory_utils.h"
+
+/* This is not yet right for how to run a test;  need to register tests, etc. */
+
+void test_thread (struct test_result_t *ret) {
+    psa_status_t crypto_status;  // result from Crypto calls
+    psa_status_t sst_status;
+
+    /* To prevent unused variable warning, as the variable might not be used
+     * in this testcase
+     */
+    (void)sst_status;
+
+    crypto_status = psa_crypto_init();
+    if (crypto_status != PSA_SUCCESS) {
+        TEST_FAIL("Could not initialize Crypto.");
+        return;
+    }
+
+    TEST_LOG("Test to show that TF-Fuzz can infer results");
+
+
+    /* Variables (etc.) to initialize and check PSA assets: */
+    static uint8_t jonathan_data[] = "I am the man";
+    static int jonathan_data_size = 12;
+
+
+    /* PSA calls to test: */
+
+    /* Creating SST asset "jonathan," with data "I am the m...". */
+    sst_status = psa_ps_set(@@@001@@@, jonathan_data_size, jonathan_data,
+                            PSA_STORAGE_FLAG_********);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+        return;
+    }
+
+
+    /* Removing assets left over from testing: */
+    psa_ps_remove(@@@001@@@);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to tear down an SST asset upon test completion.");
+        return;
+    }
+
+    /* Test completed */
+    ret->val = TEST_PASSED;
+}
diff --git a/tools/tf_fuzz/regression/000003_set_sst_name_data/template b/tools/tf_fuzz/regression/000003_set_sst_name_data/template
new file mode 100644
index 0000000..53b8897
--- /dev/null
+++ b/tools/tf_fuzz/regression/000003_set_sst_name_data/template
@@ -0,0 +1,2 @@
+purpose to show that TF-Fuzz can infer results;
+set sst name jonathan data "I am the man";
diff --git a/tools/tf_fuzz/regression/000004_set_sst_name_rand_data/check.py b/tools/tf_fuzz/regression/000004_set_sst_name_rand_data/check.py
new file mode 100644
index 0000000..a215e77
--- /dev/null
+++ b/tools/tf_fuzz/regression/000004_set_sst_name_rand_data/check.py
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+import sys, os
+
+def main():
+    if len(sys.argv) != 4:
+        print >> sys.stderr, "%s requires 3 command-line arguments. Exiting." % sys.argv[0]
+        sys.exit(1)
+
+    #print "Command line args: %s" % (', '.join(sys.argv[1:4]))
+    sys.exit(0)
+
+if __name__ == "__main__":
+    main()
diff --git a/tools/tf_fuzz/regression/000004_set_sst_name_rand_data/exp_stdout_stderr b/tools/tf_fuzz/regression/000004_set_sst_name_rand_data/exp_stdout_stderr
new file mode 100644
index 0000000..c719302
--- /dev/null
+++ b/tools/tf_fuzz/regression/000004_set_sst_name_rand_data/exp_stdout_stderr
@@ -0,0 +1,17 @@
+Trusted Firmware Fuzzer (TF-Fuzz) starting...
+
+Info:  random seed was not specified.
+
+Using seed value of \d+ \(0x[a-f\d]+\).
+Purpose line:  to show how to randomize data
+ASSET_IDENTIFIER:  "gibberish"
+SST-asset identifier list:  "data"
+SST-create from random data
+Set SST command:  "*"
+Set command:  "*"
+Command with no expect:  ";"
+Lines:  Line number 3.
+Lines:  Line number 3.
+Writing test file, test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tools/tf_fuzz/regression/000004_set_sst_name_rand_data/exp_test.c b/tools/tf_fuzz/regression/000004_set_sst_name_rand_data/exp_test.c
new file mode 100644
index 0000000..f4743ea
--- /dev/null
+++ b/tools/tf_fuzz/regression/000004_set_sst_name_rand_data/exp_test.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/*
+ * Test purpose:
+ *     to show how to randomize data
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "../sst/non_secure/ns_test_helpers.h"
+#include "psa/protected_storage.h"
+#include "test/framework/test_framework_helpers.h"
+#include "crypto_tests_common.h"
+#include "tfm_memory_utils.h"
+
+/* This is not yet right for how to run a test;  need to register tests, etc. */
+
+void test_thread (struct test_result_t *ret) {
+    psa_status_t crypto_status;  // result from Crypto calls
+    psa_status_t sst_status;
+
+    /* To prevent unused variable warning, as the variable might not be used
+     * in this testcase
+     */
+    (void)sst_status;
+
+    crypto_status = psa_crypto_init();
+    if (crypto_status != PSA_SUCCESS) {
+        TEST_FAIL("Could not initialize Crypto.");
+        return;
+    }
+
+    TEST_LOG("Test to show how to randomize data");
+
+
+    /* Variables (etc.) to initialize and check PSA assets: */
+    static uint8_t gibberish_data[] = "@@002@10@@********";
+    static int gibberish_data_size = \d+;
+
+
+    /* PSA calls to test: */
+
+    /* Creating SST asset "gibberish," with data "@@002@10@@...". */
+    sst_status = psa_ps_set(@@@001@@@, gibberish_data_size, gibberish_data,
+                            PSA_STORAGE_FLAG_********);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+        return;
+    }
+
+
+    /* Removing assets left over from testing: */
+    psa_ps_remove(@@@001@@@);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to tear down an SST asset upon test completion.");
+        return;
+    }
+
+    /* Test completed */
+    ret->val = TEST_PASSED;
+}
diff --git a/tools/tf_fuzz/regression/000004_set_sst_name_rand_data/template b/tools/tf_fuzz/regression/000004_set_sst_name_rand_data/template
new file mode 100644
index 0000000..912c23a
--- /dev/null
+++ b/tools/tf_fuzz/regression/000004_set_sst_name_rand_data/template
@@ -0,0 +1,2 @@
+purpose to show how to randomize data;
+set sst name gibberish data *;
diff --git a/tools/tf_fuzz/regression/000005_set_sst_rand_name_rand_data/check.py b/tools/tf_fuzz/regression/000005_set_sst_rand_name_rand_data/check.py
new file mode 100644
index 0000000..a215e77
--- /dev/null
+++ b/tools/tf_fuzz/regression/000005_set_sst_rand_name_rand_data/check.py
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+import sys, os
+
+def main():
+    if len(sys.argv) != 4:
+        print >> sys.stderr, "%s requires 3 command-line arguments. Exiting." % sys.argv[0]
+        sys.exit(1)
+
+    #print "Command line args: %s" % (', '.join(sys.argv[1:4]))
+    sys.exit(0)
+
+if __name__ == "__main__":
+    main()
diff --git a/tools/tf_fuzz/regression/000005_set_sst_rand_name_rand_data/exp_stdout_stderr b/tools/tf_fuzz/regression/000005_set_sst_rand_name_rand_data/exp_stdout_stderr
new file mode 100644
index 0000000..466f250
--- /dev/null
+++ b/tools/tf_fuzz/regression/000005_set_sst_rand_name_rand_data/exp_stdout_stderr
@@ -0,0 +1,16 @@
+Trusted Firmware Fuzzer (TF-Fuzz) starting...
+
+Info:  random seed was not specified.
+
+Using seed value of \d+ \(0x[a-f\d]+\).
+Purpose line:  to show how to randomize name and data
+SST-asset random identifier:  "*"
+SST-create from random data
+Set SST command:  "*"
+Set command:  "*"
+Command with no expect:  ";"
+Lines:  Line number 3.
+Lines:  Line number 3.
+Writing test file, test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tools/tf_fuzz/regression/000005_set_sst_rand_name_rand_data/exp_test.c b/tools/tf_fuzz/regression/000005_set_sst_rand_name_rand_data/exp_test.c
new file mode 100644
index 0000000..238af07
--- /dev/null
+++ b/tools/tf_fuzz/regression/000005_set_sst_rand_name_rand_data/exp_test.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/*
+ * Test purpose:
+ *     to show how to randomize name and data
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "../sst/non_secure/ns_test_helpers.h"
+#include "psa/protected_storage.h"
+#include "test/framework/test_framework_helpers.h"
+#include "crypto_tests_common.h"
+#include "tfm_memory_utils.h"
+
+/* This is not yet right for how to run a test;  need to register tests, etc. */
+
+void test_thread (struct test_result_t *ret) {
+    psa_status_t crypto_status;  // result from Crypto calls
+    psa_status_t sst_status;
+
+    /* To prevent unused variable warning, as the variable might not be used
+     * in this testcase
+     */
+    (void)sst_status;
+
+    crypto_status = psa_crypto_init();
+    if (crypto_status != PSA_SUCCESS) {
+        TEST_FAIL("Could not initialize Crypto.");
+        return;
+    }
+
+    TEST_LOG("Test to show how to randomize name and data");
+
+
+    /* Variables (etc.) to initialize and check PSA assets: */
+    static uint8_t @@@003@@@_data[] = "@@002@10@@********";
+    static int @@@003@@@_data_size = \d+;
+
+
+    /* PSA calls to test: */
+
+    /* Creating SST asset "@@@003@@@," with data "@@002@10@@...". */
+    sst_status = psa_ps_set(@@@001@@@, @@@003@@@_data_size, @@@003@@@_data,
+                            PSA_STORAGE_FLAG_********);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+        return;
+    }
+
+
+    /* Removing assets left over from testing: */
+    psa_ps_remove(@@@001@@@);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to tear down an SST asset upon test completion.");
+        return;
+    }
+
+    /* Test completed */
+    ret->val = TEST_PASSED;
+}
diff --git a/tools/tf_fuzz/regression/000005_set_sst_rand_name_rand_data/template b/tools/tf_fuzz/regression/000005_set_sst_rand_name_rand_data/template
new file mode 100644
index 0000000..5290f27
--- /dev/null
+++ b/tools/tf_fuzz/regression/000005_set_sst_rand_name_rand_data/template
@@ -0,0 +1,2 @@
+purpose to show how to randomize name and data;
+set sst name * data *;
diff --git a/tools/tf_fuzz/regression/000006_set_sst_multi_name_rand_data/check.py b/tools/tf_fuzz/regression/000006_set_sst_multi_name_rand_data/check.py
new file mode 100644
index 0000000..a215e77
--- /dev/null
+++ b/tools/tf_fuzz/regression/000006_set_sst_multi_name_rand_data/check.py
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+import sys, os
+
+def main():
+    if len(sys.argv) != 4:
+        print >> sys.stderr, "%s requires 3 command-line arguments. Exiting." % sys.argv[0]
+        sys.exit(1)
+
+    #print "Command line args: %s" % (', '.join(sys.argv[1:4]))
+    sys.exit(0)
+
+if __name__ == "__main__":
+    main()
diff --git a/tools/tf_fuzz/regression/000006_set_sst_multi_name_rand_data/exp_stdout_stderr b/tools/tf_fuzz/regression/000006_set_sst_multi_name_rand_data/exp_stdout_stderr
new file mode 100644
index 0000000..1f090d1
--- /dev/null
+++ b/tools/tf_fuzz/regression/000006_set_sst_multi_name_rand_data/exp_stdout_stderr
@@ -0,0 +1,21 @@
+Trusted Firmware Fuzzer (TF-Fuzz) starting...
+
+Info:  random seed was not specified.
+
+Using seed value of \d+ \(0x[a-f\d]+\).
+Purpose line:  to show a nice party trick
+ASSET_IDENTIFIER:  "john"
+ASSET_IDENTIFIER:  "paul"
+ASSET_IDENTIFIER:  "george"
+ASSET_IDENTIFIER:  "and"
+ASSET_IDENTIFIER:  "ringo"
+SST-asset identifier list:  "data"
+SST-create from random data
+Set SST command:  "*"
+Set command:  "*"
+Command with no expect:  ";"
+Lines:  Line number 3.
+Lines:  Line number 3.
+Writing test file, test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tools/tf_fuzz/regression/000006_set_sst_multi_name_rand_data/exp_test.c b/tools/tf_fuzz/regression/000006_set_sst_multi_name_rand_data/exp_test.c
new file mode 100644
index 0000000..3950c58
--- /dev/null
+++ b/tools/tf_fuzz/regression/000006_set_sst_multi_name_rand_data/exp_test.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/*
+ * Test purpose:
+ *     to show a nice party trick
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "../sst/non_secure/ns_test_helpers.h"
+#include "psa/protected_storage.h"
+#include "test/framework/test_framework_helpers.h"
+#include "crypto_tests_common.h"
+#include "tfm_memory_utils.h"
+
+/* This is not yet right for how to run a test;  need to register tests, etc. */
+
+void test_thread (struct test_result_t *ret) {
+    psa_status_t crypto_status;  // result from Crypto calls
+    psa_status_t sst_status;
+
+    /* To prevent unused variable warning, as the variable might not be used
+     * in this testcase
+     */
+    (void)sst_status;
+
+    crypto_status = psa_crypto_init();
+    if (crypto_status != PSA_SUCCESS) {
+        TEST_FAIL("Could not initialize Crypto.");
+        return;
+    }
+
+    TEST_LOG("Test to show a nice party trick");
+
+
+    /* Variables (etc.) to initialize and check PSA assets: */
+    static uint8_t john_data[] = "@@012@10@@********";
+    static int john_data_size = \d+;
+    static uint8_t paul_data[] = "@@013@10@@********";
+    static int paul_data_size = \d+;
+    static uint8_t george_data[] = "@@014@10@@********";
+    static int george_data_size = \d+;
+    static uint8_t and_data[] = "@@015@10@@********";
+    static int and_data_size = \d+;
+    static uint8_t ringo_data[] = "@@016@10@@********";
+    static int ringo_data_size = \d+;
+
+
+    /* PSA calls to test: */
+
+    /* Creating SST asset "john," with data "@@012@10@@...". */
+    sst_status = psa_ps_set(@@@001@@@, john_data_size, john_data,
+                            PSA_STORAGE_FLAG_********);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+        return;
+    }
+
+    /* Creating SST asset "paul," with data "@@013@10@@...". */
+    sst_status = psa_ps_set(@@@002@@@, paul_data_size, paul_data,
+                            PSA_STORAGE_FLAG_********);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+        return;
+    }
+
+    /* Creating SST asset "george," with data "@@014@10@@...". */
+    sst_status = psa_ps_set(@@@003@@@, george_data_size, george_data,
+                            PSA_STORAGE_FLAG_********);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+        return;
+    }
+
+    /* Creating SST asset "and," with data "@@015@10@@...". */
+    sst_status = psa_ps_set(@@@004@@@, and_data_size, and_data,
+                            PSA_STORAGE_FLAG_********);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+        return;
+    }
+
+    /* Creating SST asset "ringo," with data "@@016@10@@...". */
+    sst_status = psa_ps_set(@@@005@@@, ringo_data_size, ringo_data,
+                            PSA_STORAGE_FLAG_********);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+        return;
+    }
+
+
+    /* Removing assets left over from testing: */
+    psa_ps_remove(@@@001@@@);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to tear down an SST asset upon test completion.");
+        return;
+    }
+    psa_ps_remove(@@@002@@@);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to tear down an SST asset upon test completion.");
+        return;
+    }
+    psa_ps_remove(@@@003@@@);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to tear down an SST asset upon test completion.");
+        return;
+    }
+    psa_ps_remove(@@@004@@@);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to tear down an SST asset upon test completion.");
+        return;
+    }
+    psa_ps_remove(@@@005@@@);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to tear down an SST asset upon test completion.");
+        return;
+    }
+
+    /* Test completed */
+    ret->val = TEST_PASSED;
+}
diff --git a/tools/tf_fuzz/regression/000006_set_sst_multi_name_rand_data/template b/tools/tf_fuzz/regression/000006_set_sst_multi_name_rand_data/template
new file mode 100644
index 0000000..2e86d75
--- /dev/null
+++ b/tools/tf_fuzz/regression/000006_set_sst_multi_name_rand_data/template
@@ -0,0 +1,2 @@
+purpose to show a nice party trick;
+set sst name john paul george and ringo data *;
diff --git a/tools/tf_fuzz/regression/000007_set_sst_multi_uid_rand_data/check.py b/tools/tf_fuzz/regression/000007_set_sst_multi_uid_rand_data/check.py
new file mode 100644
index 0000000..a215e77
--- /dev/null
+++ b/tools/tf_fuzz/regression/000007_set_sst_multi_uid_rand_data/check.py
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+import sys, os
+
+def main():
+    if len(sys.argv) != 4:
+        print >> sys.stderr, "%s requires 3 command-line arguments. Exiting." % sys.argv[0]
+        sys.exit(1)
+
+    #print "Command line args: %s" % (', '.join(sys.argv[1:4]))
+    sys.exit(0)
+
+if __name__ == "__main__":
+    main()
diff --git a/tools/tf_fuzz/regression/000007_set_sst_multi_uid_rand_data/exp_stdout_stderr b/tools/tf_fuzz/regression/000007_set_sst_multi_uid_rand_data/exp_stdout_stderr
new file mode 100644
index 0000000..226833a
--- /dev/null
+++ b/tools/tf_fuzz/regression/000007_set_sst_multi_uid_rand_data/exp_stdout_stderr
@@ -0,0 +1,22 @@
+Trusted Firmware Fuzzer (TF-Fuzz) starting...
+
+Info:  random seed was not specified.
+
+Using seed value of \d+ \(0x[a-f\d]+\).
+Purpose line:  same with UIDs
+ASSET_NUMBER:  "17"
+ASSET_NUMBER:  "19"
+ASSET_NUMBER:  "24"
+ASSET_NUMBER:  "31"
+ASSET_NUMBER:  "34"
+ASSET_NUMBER:  "41"
+SST-asset UID list:  "data"
+SST-create from random data
+Set SST command:  "*"
+Set command:  "*"
+Command with no expect:  ";"
+Lines:  Line number 3.
+Lines:  Line number 3.
+Writing test file, test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tools/tf_fuzz/regression/000007_set_sst_multi_uid_rand_data/exp_test.c b/tools/tf_fuzz/regression/000007_set_sst_multi_uid_rand_data/exp_test.c
new file mode 100644
index 0000000..98a2c17
--- /dev/null
+++ b/tools/tf_fuzz/regression/000007_set_sst_multi_uid_rand_data/exp_test.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/*
+ * Test purpose:
+ *     same with UIDs
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "../sst/non_secure/ns_test_helpers.h"
+#include "psa/protected_storage.h"
+#include "test/framework/test_framework_helpers.h"
+#include "crypto_tests_common.h"
+#include "tfm_memory_utils.h"
+
+/* This is not yet right for how to run a test;  need to register tests, etc. */
+
+void test_thread (struct test_result_t *ret) {
+    psa_status_t crypto_status;  // result from Crypto calls
+    psa_status_t sst_status;
+
+    /* To prevent unused variable warning, as the variable might not be used
+     * in this testcase
+     */
+    (void)sst_status;
+
+    crypto_status = psa_crypto_init();
+    if (crypto_status != PSA_SUCCESS) {
+        TEST_FAIL("Could not initialize Crypto.");
+        return;
+    }
+
+    TEST_LOG("Test same with UIDs");
+
+
+    /* Variables (etc.) to initialize and check PSA assets: */
+    static uint8_t SST_ID_17_data[] = "@@012@10@@********";
+    static int SST_ID_17_data_size = \d+;
+    static uint8_t SST_ID_19_data[] = "@@013@10@@********";
+    static int SST_ID_19_data_size = \d+;
+    static uint8_t SST_ID_24_data[] = "@@014@10@@********";
+    static int SST_ID_24_data_size = \d+;
+    static uint8_t SST_ID_31_data[] = "@@015@10@@********";
+    static int SST_ID_31_data_size = \d+;
+    static uint8_t SST_ID_34_data[] = "@@016@10@@********";
+    static int SST_ID_34_data_size = \d+;
+    static uint8_t SST_ID_41_data[] = "@@017@10@@********";
+    static int SST_ID_41_data_size = \d+;
+
+
+    /* PSA calls to test: */
+
+    /* Creating SST asset UID = 17 with data "@@012@10@@...". */
+    sst_status = psa_ps_set(17, SST_ID_17_data_size, SST_ID_17_data,
+                            PSA_STORAGE_FLAG_********);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+        return;
+    }
+
+    /* Creating SST asset UID = 19 with data "@@013@10@@...". */
+    sst_status = psa_ps_set(19, SST_ID_19_data_size, SST_ID_19_data,
+                            PSA_STORAGE_FLAG_********);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+        return;
+    }
+
+    /* Creating SST asset UID = 24 with data "@@014@10@@...". */
+    sst_status = psa_ps_set(24, SST_ID_24_data_size, SST_ID_24_data,
+                            PSA_STORAGE_FLAG_********);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+        return;
+    }
+
+    /* Creating SST asset UID = 31 with data "@@015@10@@...". */
+    sst_status = psa_ps_set(31, SST_ID_31_data_size, SST_ID_31_data,
+                            PSA_STORAGE_FLAG_********);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+        return;
+    }
+
+    /* Creating SST asset UID = 34 with data "@@016@10@@...". */
+    sst_status = psa_ps_set(34, SST_ID_34_data_size, SST_ID_34_data,
+                            PSA_STORAGE_FLAG_********);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+        return;
+    }
+
+    /* Creating SST asset UID = 41 with data "@@017@10@@...". */
+    sst_status = psa_ps_set(41, SST_ID_41_data_size, SST_ID_41_data,
+                            PSA_STORAGE_FLAG_********);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+        return;
+    }
+
+
+    /* Removing assets left over from testing: */
+    psa_ps_remove(17);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to tear down an SST asset upon test completion.");
+        return;
+    }
+    psa_ps_remove(19);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to tear down an SST asset upon test completion.");
+        return;
+    }
+    psa_ps_remove(24);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to tear down an SST asset upon test completion.");
+        return;
+    }
+    psa_ps_remove(31);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to tear down an SST asset upon test completion.");
+        return;
+    }
+    psa_ps_remove(34);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to tear down an SST asset upon test completion.");
+        return;
+    }
+    psa_ps_remove(41);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to tear down an SST asset upon test completion.");
+        return;
+    }
+
+    /* Test completed */
+    ret->val = TEST_PASSED;
+}
diff --git a/tools/tf_fuzz/regression/000007_set_sst_multi_uid_rand_data/template b/tools/tf_fuzz/regression/000007_set_sst_multi_uid_rand_data/template
new file mode 100644
index 0000000..903027e
--- /dev/null
+++ b/tools/tf_fuzz/regression/000007_set_sst_multi_uid_rand_data/template
@@ -0,0 +1,2 @@
+purpose same with UIDs;
+set sst uid 17 19 24 31 34 41 data *;
diff --git a/tools/tf_fuzz/regression/000008_set_sst_name_rand_data_read_check_wrong/check.py b/tools/tf_fuzz/regression/000008_set_sst_name_rand_data_read_check_wrong/check.py
new file mode 100644
index 0000000..a215e77
--- /dev/null
+++ b/tools/tf_fuzz/regression/000008_set_sst_name_rand_data_read_check_wrong/check.py
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+import sys, os
+
+def main():
+    if len(sys.argv) != 4:
+        print >> sys.stderr, "%s requires 3 command-line arguments. Exiting." % sys.argv[0]
+        sys.exit(1)
+
+    #print "Command line args: %s" % (', '.join(sys.argv[1:4]))
+    sys.exit(0)
+
+if __name__ == "__main__":
+    main()
diff --git a/tools/tf_fuzz/regression/000008_set_sst_name_rand_data_read_check_wrong/exp_stdout_stderr b/tools/tf_fuzz/regression/000008_set_sst_name_rand_data_read_check_wrong/exp_stdout_stderr
new file mode 100644
index 0000000..eeed4bc
--- /dev/null
+++ b/tools/tf_fuzz/regression/000008_set_sst_name_rand_data_read_check_wrong/exp_stdout_stderr
@@ -0,0 +1,25 @@
+Trusted Firmware Fuzzer (TF-Fuzz) starting...
+
+Info:  random seed was not specified.
+
+Using seed value of \d+ \(0x[a-f\d]+\).
+Purpose line:  to create and show an asset
+ASSET_IDENTIFIER:  "snortwaggle"
+SST-asset identifier list:  "data"
+SST-create from random data
+Set SST command:  "*"
+Set command:  "*"
+Command with no expect:  ";"
+ASSET_IDENTIFIER:  "snortwaggle"
+SST-asset identifier list:  "check"
+LITERAL:  "almost certainly not *this*"
+SST-read check against literal:  "almost certainly not *this*"
+Read SST command:  ""almost certainly not *this*""
+Read command:  ""almost certainly not *this*""
+Command with no expect:  ";"
+Lines:  Line number 4.
+Lines:  Line number 4.
+Lines:  Line number 4.
+Writing test file, test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tools/tf_fuzz/regression/000008_set_sst_name_rand_data_read_check_wrong/exp_test.c b/tools/tf_fuzz/regression/000008_set_sst_name_rand_data_read_check_wrong/exp_test.c
new file mode 100644
index 0000000..0d304f8
--- /dev/null
+++ b/tools/tf_fuzz/regression/000008_set_sst_name_rand_data_read_check_wrong/exp_test.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/*
+ * Test purpose:
+ *     to create and show an asset
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "../sst/non_secure/ns_test_helpers.h"
+#include "psa/protected_storage.h"
+#include "test/framework/test_framework_helpers.h"
+#include "crypto_tests_common.h"
+#include "tfm_memory_utils.h"
+
+/* This is not yet right for how to run a test;  need to register tests, etc. */
+
+void test_thread (struct test_result_t *ret) {
+    psa_status_t crypto_status;  // result from Crypto calls
+    psa_status_t sst_status;
+
+    /* To prevent unused variable warning, as the variable might not be used
+     * in this testcase
+     */
+    (void)sst_status;
+
+    crypto_status = psa_crypto_init();
+    if (crypto_status != PSA_SUCCESS) {
+        TEST_FAIL("Could not initialize Crypto.");
+        return;
+    }
+
+    TEST_LOG("Test to create and show an asset");
+
+
+    /* Variables (etc.) to initialize and check PSA assets: */
+    static uint8_t snortwaggle_data[] = "@@002@10@@********";
+    static int snortwaggle_data_size = \d+;
+    static uint8_t snortwaggle_exp_data[] = "almost certainly not *this*";
+    static uint8_t snortwaggle_act_data[2048] = "********";
+    static size_t snortwaggle_act_length = 0;
+
+
+    /* PSA calls to test: */
+
+    /* Creating SST asset "snortwaggle," with data "@@002@10@@...". */
+    sst_status = psa_ps_set(@@@001@@@, snortwaggle_data_size, snortwaggle_data,
+                            PSA_STORAGE_FLAG_********);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+        return;
+    }
+
+    sst_status = psa_ps_get(@@@001@@@, 0, 0, snortwaggle_act_data
+                            &snortwaggle_act_length);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("psa_ps_get() expected PSA_SUCCESS.");
+        return;
+    }
+    /* Check that the data is correct */
+    if (tfm_memcmp(snortwaggle_act_data, snortwaggle_exp_data, 27) != 0) {
+        TEST_FAIL("Read data should be equal to result data");
+        return;
+    }
+
+
+    /* Removing assets left over from testing: */
+    psa_ps_remove(@@@001@@@);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to tear down an SST asset upon test completion.");
+        return;
+    }
+
+    /* Test completed */
+    ret->val = TEST_PASSED;
+}
diff --git a/tools/tf_fuzz/regression/000008_set_sst_name_rand_data_read_check_wrong/template b/tools/tf_fuzz/regression/000008_set_sst_name_rand_data_read_check_wrong/template
new file mode 100644
index 0000000..adaacfc
--- /dev/null
+++ b/tools/tf_fuzz/regression/000008_set_sst_name_rand_data_read_check_wrong/template
@@ -0,0 +1,3 @@
+purpose to create and show an asset;
+set sst name snortwaggle data *;
+read sst name snortwaggle check "almost certainly not *this*";
diff --git a/tools/tf_fuzz/regression/000009_set_sst_name_rand_data_read_check_var_read_print/check.py b/tools/tf_fuzz/regression/000009_set_sst_name_rand_data_read_check_var_read_print/check.py
new file mode 100644
index 0000000..a215e77
--- /dev/null
+++ b/tools/tf_fuzz/regression/000009_set_sst_name_rand_data_read_check_var_read_print/check.py
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+import sys, os
+
+def main():
+    if len(sys.argv) != 4:
+        print >> sys.stderr, "%s requires 3 command-line arguments. Exiting." % sys.argv[0]
+        sys.exit(1)
+
+    #print "Command line args: %s" % (', '.join(sys.argv[1:4]))
+    sys.exit(0)
+
+if __name__ == "__main__":
+    main()
diff --git a/tools/tf_fuzz/regression/000009_set_sst_name_rand_data_read_check_var_read_print/exp_stdout_stderr b/tools/tf_fuzz/regression/000009_set_sst_name_rand_data_read_check_var_read_print/exp_stdout_stderr
new file mode 100644
index 0000000..5f3d60b
--- /dev/null
+++ b/tools/tf_fuzz/regression/000009_set_sst_name_rand_data_read_check_var_read_print/exp_stdout_stderr
@@ -0,0 +1,33 @@
+Trusted Firmware Fuzzer (TF-Fuzz) starting...
+
+Info:  random seed was not specified.
+
+Using seed value of \d+ \(0x[a-f\d]+\).
+Purpose line:  to dump to a variable or to the log
+ASSET_IDENTIFIER:  "greebledorf"
+SST-asset identifier list:  "data"
+SST-create from random data
+Set SST command:  "*"
+Set command:  "*"
+Command with no expect:  ";"
+ASSET_IDENTIFIER:  "greebledorf"
+SST-asset identifier list:  "check"
+IDENTIFIER:  "a_variable"
+SST-read-arguments variable name:  "a_variable"
+SST-read check against variable:  "a_variable"
+Read SST command:  "a_variable"
+Read command:  "a_variable"
+Command with no expect:  ";"
+ASSET_IDENTIFIER:  "greebledorf"
+SST-asset identifier list:  "print"
+SST-read log to test log:  "print"
+Read SST command:  "print"
+Read command:  "print"
+Command with no expect:  ";"
+Lines:  Line number 5.
+Lines:  Line number 5.
+Lines:  Line number 5.
+Lines:  Line number 5.
+Writing test file, test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tools/tf_fuzz/regression/000009_set_sst_name_rand_data_read_check_var_read_print/exp_test.c b/tools/tf_fuzz/regression/000009_set_sst_name_rand_data_read_check_var_read_print/exp_test.c
new file mode 100644
index 0000000..4c5b171
--- /dev/null
+++ b/tools/tf_fuzz/regression/000009_set_sst_name_rand_data_read_check_var_read_print/exp_test.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/*
+ * Test purpose:
+ *     to dump to a variable or to the log
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "../sst/non_secure/ns_test_helpers.h"
+#include "psa/protected_storage.h"
+#include "test/framework/test_framework_helpers.h"
+#include "crypto_tests_common.h"
+#include "tfm_memory_utils.h"
+
+/* This is not yet right for how to run a test;  need to register tests, etc. */
+
+void test_thread (struct test_result_t *ret) {
+    psa_status_t crypto_status;  // result from Crypto calls
+    psa_status_t sst_status;
+
+    /* To prevent unused variable warning, as the variable might not be used
+     * in this testcase
+     */
+    (void)sst_status;
+
+    crypto_status = psa_crypto_init();
+    if (crypto_status != PSA_SUCCESS) {
+        TEST_FAIL("Could not initialize Crypto.");
+        return;
+    }
+
+    TEST_LOG("Test to dump to a variable or to the log");
+
+
+    /* Variables (etc.) to initialize and check PSA assets: */
+    static uint8_t greebledorf_data[] = "@@002@10@@********";
+    static int greebledorf_data_size = \d+;
+    static uint8_t a_variable[] = "";
+    static uint8_t greebledorf_act_data[2048] = "********";
+    static int greebledorf_act_length = 0;
+    static uint8_t greebledorf_act_data[2048] = "********";
+    static int greebledorf_act_length = 0;
+
+
+    /* PSA calls to test: */
+
+    /* Creating SST asset "greebledorf," with data "@@002@10@@...". */
+    sst_status = psa_ps_set(@@@001@@@, greebledorf_data_size, greebledorf_data,
+                            PSA_STORAGE_FLAG_********);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+        return;
+    }
+
+    sst_status = psa_ps_get(@@@001@@@, 0, 0, greebledorf_act_data,
+                            &greebledorf_act_length);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("psa_ps_get() expected PSA_SUCCESS.");
+        return;
+    }
+    /* Check that the data is correct */
+    if (tfm_memcmp(greebledorf_act_data, a_variable, 0) != 0) {
+        TEST_FAIL("Read data should be equal to result data");
+        return;
+    }
+
+    sst_status = psa_ps_get(@@@001@@@, 0, 0, greebledorf_act_data,
+                            &greebledorf_act_length);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("psa_ps_get() expected PSA_SUCCESS.");
+        return;
+    }
+    TEST_LOG(greebledorf_act_data);
+
+
+    /* Removing assets left over from testing: */
+    psa_ps_remove(@@@001@@@);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to tear down an SST asset upon test completion.");
+        return;
+    }
+
+    /* Test completed */
+    ret->val = TEST_PASSED;
+}
diff --git a/tools/tf_fuzz/regression/000009_set_sst_name_rand_data_read_check_var_read_print/template b/tools/tf_fuzz/regression/000009_set_sst_name_rand_data_read_check_var_read_print/template
new file mode 100644
index 0000000..72cc269
--- /dev/null
+++ b/tools/tf_fuzz/regression/000009_set_sst_name_rand_data_read_check_var_read_print/template
@@ -0,0 +1,4 @@
+purpose to dump to a variable or to the log;
+set sst name greebledorf data *;
+read sst name greebledorf check a_variable;
+read sst name greebledorf print;
diff --git a/tools/tf_fuzz/regression/000010_read_nonexistent_sst_check_string/check.py b/tools/tf_fuzz/regression/000010_read_nonexistent_sst_check_string/check.py
new file mode 100644
index 0000000..a215e77
--- /dev/null
+++ b/tools/tf_fuzz/regression/000010_read_nonexistent_sst_check_string/check.py
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+import sys, os
+
+def main():
+    if len(sys.argv) != 4:
+        print >> sys.stderr, "%s requires 3 command-line arguments. Exiting." % sys.argv[0]
+        sys.exit(1)
+
+    #print "Command line args: %s" % (', '.join(sys.argv[1:4]))
+    sys.exit(0)
+
+if __name__ == "__main__":
+    main()
diff --git a/tools/tf_fuzz/regression/000010_read_nonexistent_sst_check_string/exp_stdout_stderr b/tools/tf_fuzz/regression/000010_read_nonexistent_sst_check_string/exp_stdout_stderr
new file mode 100644
index 0000000..ba723fe
--- /dev/null
+++ b/tools/tf_fuzz/regression/000010_read_nonexistent_sst_check_string/exp_stdout_stderr
@@ -0,0 +1,18 @@
+Trusted Firmware Fuzzer (TF-Fuzz) starting...
+
+Info:  random seed was not specified.
+
+Using seed value of \d+ \(0x[a-f\d]+\).
+Purpose line:  to show what happens when you 'read' a non-existent asset
+ASSET_IDENTIFIER:  "napoleon"
+SST-asset identifier list:  "check"
+LITERAL:  "this won't work"
+SST-read check against literal:  "this won't work"
+Read SST command:  ""this won't work""
+Read command:  ""this won't work""
+Command with no expect:  ";"
+Lines:  Line number 3.
+Lines:  Line number 3.
+Writing test file, test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tools/tf_fuzz/regression/000010_read_nonexistent_sst_check_string/exp_test.c b/tools/tf_fuzz/regression/000010_read_nonexistent_sst_check_string/exp_test.c
new file mode 100644
index 0000000..7916d41
--- /dev/null
+++ b/tools/tf_fuzz/regression/000010_read_nonexistent_sst_check_string/exp_test.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/*
+ * Test purpose:
+ *     to show what happens when you 'read' a non-existent asset
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "../sst/non_secure/ns_test_helpers.h"
+#include "psa/protected_storage.h"
+#include "test/framework/test_framework_helpers.h"
+#include "crypto_tests_common.h"
+#include "tfm_memory_utils.h"
+
+/* This is not yet right for how to run a test;  need to register tests, etc. */
+
+void test_thread (struct test_result_t *ret) {
+    psa_status_t crypto_status;  // result from Crypto calls
+    psa_status_t sst_status;
+
+    /* To prevent unused variable warning, as the variable might not be used
+     * in this testcase
+     */
+    (void)sst_status;
+
+    crypto_status = psa_crypto_init();
+    if (crypto_status != PSA_SUCCESS) {
+        TEST_FAIL("Could not initialize Crypto.");
+        return;
+    }
+
+    TEST_LOG("Test to show what happens when you 'read' a non-existent asset");
+
+
+    /* Variables (etc.) to initialize and check PSA assets: */
+    static uint8_t napoleon_exp_data[] = "this won't work";
+    static uint8_t napoleon_act_data[2048] = "********";
+    static int napoleon_act_length = 0;
+
+
+    /* PSA calls to test: */
+
+    sst_status = psa_ps_get(********, 0, 0, napoleon_act_data
+                            &napoleon_act_length);
+    if (sst_status != PSA_ERROR_DOES_NOT_EXIST) {
+        TEST_FAIL("psa_ps_get() expected PSA_ERROR_DOES_NOT_EXIST.");
+        return;
+    }
+    /* Check that the data is correct */
+    if (tfm_memcmp(napoleon_act_data, napoleon_exp_data, ********) != 0) {
+        TEST_FAIL("Read data should be equal to result data");
+        return;
+    }
+
+
+    /* Removing assets left over from testing: */
+
+    /* Test completed */
+    ret->val = TEST_PASSED;
+}
diff --git a/tools/tf_fuzz/regression/000010_read_nonexistent_sst_check_string/template b/tools/tf_fuzz/regression/000010_read_nonexistent_sst_check_string/template
new file mode 100644
index 0000000..3e70099
--- /dev/null
+++ b/tools/tf_fuzz/regression/000010_read_nonexistent_sst_check_string/template
@@ -0,0 +1,2 @@
+purpose to show what happens when you 'read' a non-existent asset;
+read sst name napoleon check "this won't work";
diff --git a/tools/tf_fuzz/regression/000011_read_nonexistent_sst_check_string_expect_pass/check.py b/tools/tf_fuzz/regression/000011_read_nonexistent_sst_check_string_expect_pass/check.py
new file mode 100644
index 0000000..a215e77
--- /dev/null
+++ b/tools/tf_fuzz/regression/000011_read_nonexistent_sst_check_string_expect_pass/check.py
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+import sys, os
+
+def main():
+    if len(sys.argv) != 4:
+        print >> sys.stderr, "%s requires 3 command-line arguments. Exiting." % sys.argv[0]
+        sys.exit(1)
+
+    #print "Command line args: %s" % (', '.join(sys.argv[1:4]))
+    sys.exit(0)
+
+if __name__ == "__main__":
+    main()
diff --git a/tools/tf_fuzz/regression/000011_read_nonexistent_sst_check_string_expect_pass/exp_stdout_stderr b/tools/tf_fuzz/regression/000011_read_nonexistent_sst_check_string_expect_pass/exp_stdout_stderr
new file mode 100644
index 0000000..018ae91
--- /dev/null
+++ b/tools/tf_fuzz/regression/000011_read_nonexistent_sst_check_string_expect_pass/exp_stdout_stderr
@@ -0,0 +1,19 @@
+Trusted Firmware Fuzzer (TF-Fuzz) starting...
+
+Info:  random seed was not specified.
+
+Using seed value of \d+ \(0x[a-f\d]+\).
+Purpose line:  to illustrate that you can override TF-Fuzz's expected result
+ASSET_IDENTIFIER:  "napoleon"
+SST-asset identifier list:  "check"
+LITERAL:  "this won't work"
+SST-read check against literal:  "this won't work"
+Read SST command:  ""this won't work""
+Read command:  ""this won't work""
+Expect pass clause:  "pass"
+Command with expect:  ";"
+Lines:  Line number 3.
+Lines:  Line number 3.
+Writing test file, test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tools/tf_fuzz/regression/000011_read_nonexistent_sst_check_string_expect_pass/exp_test.c b/tools/tf_fuzz/regression/000011_read_nonexistent_sst_check_string_expect_pass/exp_test.c
new file mode 100644
index 0000000..277f7c3
--- /dev/null
+++ b/tools/tf_fuzz/regression/000011_read_nonexistent_sst_check_string_expect_pass/exp_test.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/*
+ * Test purpose:
+ *     to illustrate that you can override TF-Fuzz's expected result
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "../sst/non_secure/ns_test_helpers.h"
+#include "psa/protected_storage.h"
+#include "test/framework/test_framework_helpers.h"
+#include "crypto_tests_common.h"
+#include "tfm_memory_utils.h"
+
+/* This is not yet right for how to run a test;  need to register tests, etc. */
+
+void test_thread (struct test_result_t *ret) {
+    psa_status_t crypto_status;  // result from Crypto calls
+    psa_status_t sst_status;
+
+    /* To prevent unused variable warning, as the variable might not be used
+     * in this testcase
+     */
+    (void)sst_status;
+
+    crypto_status = psa_crypto_init();
+    if (crypto_status != PSA_SUCCESS) {
+        TEST_FAIL("Could not initialize Crypto.");
+        return;
+    }
+
+    TEST_LOG("Test to illustrate that you can override TF-Fuzz's expected result");
+
+
+    /* Variables (etc.) to initialize and check PSA assets: */
+    static uint8_t napoleon_exp_data[] = "this won't work";
+    static uint8_t napoleon_act_data[2048] = "********";
+    static int napoleon_act_length = 0;
+
+
+    /* PSA calls to test: */
+
+    sst_status = psa_ps_get(********, 0, 0, napoleon_act_data,
+                            &napoleon_act_length);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("psa_ps_get() expected PSA_SUCCESS.");
+        return;
+    }
+    /* Check that the data is correct */
+    if (tfm_memcmp(napoleon_act_data, napoleon_exp_data, ********) != 0) {
+        TEST_FAIL("Read data should be equal to result data");
+        return;
+    }
+
+
+    /* Removing assets left over from testing: */
+
+    /* Test completed */
+    ret->val = TEST_PASSED;
+}
diff --git a/tools/tf_fuzz/regression/000011_read_nonexistent_sst_check_string_expect_pass/template b/tools/tf_fuzz/regression/000011_read_nonexistent_sst_check_string_expect_pass/template
new file mode 100644
index 0000000..5fdd0fc
--- /dev/null
+++ b/tools/tf_fuzz/regression/000011_read_nonexistent_sst_check_string_expect_pass/template
@@ -0,0 +1,2 @@
+purpose to illustrate that you can override TF-Fuzz's expected result;
+read sst name napoleon check "this won't work" expect pass;
diff --git a/tools/tf_fuzz/regression/000012_read_nonexistent_sst_check_string_expect_other/check.py b/tools/tf_fuzz/regression/000012_read_nonexistent_sst_check_string_expect_other/check.py
new file mode 100644
index 0000000..a215e77
--- /dev/null
+++ b/tools/tf_fuzz/regression/000012_read_nonexistent_sst_check_string_expect_other/check.py
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+import sys, os
+
+def main():
+    if len(sys.argv) != 4:
+        print >> sys.stderr, "%s requires 3 command-line arguments. Exiting." % sys.argv[0]
+        sys.exit(1)
+
+    #print "Command line args: %s" % (', '.join(sys.argv[1:4]))
+    sys.exit(0)
+
+if __name__ == "__main__":
+    main()
diff --git a/tools/tf_fuzz/regression/000012_read_nonexistent_sst_check_string_expect_other/exp_stdout_stderr b/tools/tf_fuzz/regression/000012_read_nonexistent_sst_check_string_expect_other/exp_stdout_stderr
new file mode 100644
index 0000000..6e9d933
--- /dev/null
+++ b/tools/tf_fuzz/regression/000012_read_nonexistent_sst_check_string_expect_other/exp_stdout_stderr
@@ -0,0 +1,20 @@
+Trusted Firmware Fuzzer (TF-Fuzz) starting...
+
+Info:  random seed was not specified.
+
+Using seed value of \d+ \(0x[a-f\d]+\).
+Purpose line:  to more-specifically override TF-Fuzz's expected result
+ASSET_IDENTIFIER:  "napoleon"
+SST-asset identifier list:  "check"
+LITERAL:  "this won't work"
+SST-read check against literal:  "this won't work"
+Read SST command:  ""this won't work""
+Read command:  ""this won't work""
+IDENTIFIER:  "PSA_ERROR_GENERIC_ERROR"
+Expect error clause:  "PSA_ERROR_GENERIC_ERROR"
+Command with expect:  ";"
+Lines:  Line number 3.
+Lines:  Line number 3.
+Writing test file, test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tools/tf_fuzz/regression/000012_read_nonexistent_sst_check_string_expect_other/exp_test.c b/tools/tf_fuzz/regression/000012_read_nonexistent_sst_check_string_expect_other/exp_test.c
new file mode 100644
index 0000000..6e66353
--- /dev/null
+++ b/tools/tf_fuzz/regression/000012_read_nonexistent_sst_check_string_expect_other/exp_test.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/*
+ * Test purpose:
+ *     to more-specifically override TF-Fuzz's expected result
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "../sst/non_secure/ns_test_helpers.h"
+#include "psa/protected_storage.h"
+#include "test/framework/test_framework_helpers.h"
+#include "crypto_tests_common.h"
+#include "tfm_memory_utils.h"
+
+/* This is not yet right for how to run a test;  need to register tests, etc. */
+
+void test_thread (struct test_result_t *ret) {
+    psa_status_t crypto_status;  // result from Crypto calls
+    psa_status_t sst_status;
+
+    /* To prevent unused variable warning, as the variable might not be used
+     * in this testcase
+     */
+    (void)sst_status;
+
+    crypto_status = psa_crypto_init();
+    if (crypto_status != PSA_SUCCESS) {
+        TEST_FAIL("Could not initialize Crypto.");
+        return;
+    }
+
+    TEST_LOG("Test to more-specifically override TF-Fuzz's expected result");
+
+
+    /* Variables (etc.) to initialize and check PSA assets: */
+    static uint8_t napoleon_exp_data[] = "this won't work";
+    static uint8_t napoleon_act_data[2048] = "********";
+    static int napoleon_act_length = 0;
+
+
+    /* PSA calls to test: */
+
+    sst_status = psa_ps_get(********, 0, 0, napoleon_act_data,
+                            &napoleon_act_length);
+    if (sst_status != PSA_ERROR_GENERIC_ERROR) {
+        TEST_FAIL("psa_ps_get() expected PSA_ERROR_GENERIC_ERROR.");
+        return;
+    }
+    /* Check that the data is correct */
+    if (tfm_memcmp(napoleon_act_data, napoleon_exp_data, ********) != 0) {
+        TEST_FAIL("Read data should be equal to result data");
+        return;
+    }
+
+
+    /* Removing assets left over from testing: */
+
+    /* Test completed */
+    ret->val = TEST_PASSED;
+}
diff --git a/tools/tf_fuzz/regression/000012_read_nonexistent_sst_check_string_expect_other/template b/tools/tf_fuzz/regression/000012_read_nonexistent_sst_check_string_expect_other/template
new file mode 100644
index 0000000..c7825c5
--- /dev/null
+++ b/tools/tf_fuzz/regression/000012_read_nonexistent_sst_check_string_expect_other/template
@@ -0,0 +1,2 @@
+purpose to more-specifically override TF-Fuzz's expected result;
+read sst name napoleon check "this won't work" expect PSA_ERROR_GENERIC_ERROR;
diff --git a/tools/tf_fuzz/regression/000013_set_sst_name_rand_data_remove_twice/check.py b/tools/tf_fuzz/regression/000013_set_sst_name_rand_data_remove_twice/check.py
new file mode 100644
index 0000000..a215e77
--- /dev/null
+++ b/tools/tf_fuzz/regression/000013_set_sst_name_rand_data_remove_twice/check.py
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+import sys, os
+
+def main():
+    if len(sys.argv) != 4:
+        print >> sys.stderr, "%s requires 3 command-line arguments. Exiting." % sys.argv[0]
+        sys.exit(1)
+
+    #print "Command line args: %s" % (', '.join(sys.argv[1:4]))
+    sys.exit(0)
+
+if __name__ == "__main__":
+    main()
diff --git a/tools/tf_fuzz/regression/000013_set_sst_name_rand_data_remove_twice/exp_stdout_stderr b/tools/tf_fuzz/regression/000013_set_sst_name_rand_data_remove_twice/exp_stdout_stderr
new file mode 100644
index 0000000..4ef68d2
--- /dev/null
+++ b/tools/tf_fuzz/regression/000013_set_sst_name_rand_data_remove_twice/exp_stdout_stderr
@@ -0,0 +1,31 @@
+Trusted Firmware Fuzzer (TF-Fuzz) starting...
+
+Info:  random seed was not specified.
+
+Using seed value of \d+ \(0x[a-f\d]+\).
+Purpose line:  to illustrate deleting assets
+ASSET_IDENTIFIER:  "george"
+SST-asset identifier list:  "data"
+SST-create from random data
+Set SST command:  "*"
+Set command:  "*"
+Command with no expect:  ";"
+ASSET_IDENTIFIER:  "george"
+SST-asset identifier list:  ";"
+SST-remove arguments:  ";"
+Remove SST command:  ";"
+Remove command:  ";"
+Command with no expect:  ";"
+ASSET_IDENTIFIER:  "george"
+SST-asset identifier list:  ";"
+SST-remove arguments:  ";"
+Remove SST command:  ";"
+Remove command:  ";"
+Command with no expect:  ";"
+Lines:  Line number 5.
+Lines:  Line number 5.
+Lines:  Line number 5.
+Lines:  Line number 5.
+Writing test file, test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tools/tf_fuzz/regression/000013_set_sst_name_rand_data_remove_twice/exp_test.c b/tools/tf_fuzz/regression/000013_set_sst_name_rand_data_remove_twice/exp_test.c
new file mode 100644
index 0000000..99b68e3
--- /dev/null
+++ b/tools/tf_fuzz/regression/000013_set_sst_name_rand_data_remove_twice/exp_test.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/*
+ * Test purpose:
+ *     to illustrate deleting assets
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "../sst/non_secure/ns_test_helpers.h"
+#include "psa/protected_storage.h"
+#include "test/framework/test_framework_helpers.h"
+#include "crypto_tests_common.h"
+#include "tfm_memory_utils.h"
+
+/* This is not yet right for how to run a test;  need to register tests, etc. */
+
+void test_thread (struct test_result_t *ret) {
+    psa_status_t crypto_status;  // result from Crypto calls
+    psa_status_t sst_status;
+
+    /* To prevent unused variable warning, as the variable might not be used
+     * in this testcase
+     */
+    (void)sst_status;
+
+    crypto_status = psa_crypto_init();
+    if (crypto_status != PSA_SUCCESS) {
+        TEST_FAIL("Could not initialize Crypto.");
+        return;
+    }
+
+    TEST_LOG("Test to illustrate deleting assets");
+
+
+    /* Variables (etc.) to initialize and check PSA assets: */
+    static uint8_t george_data[] = "@@002@10@@********";
+    static int george_data_size = \d+;
+
+
+    /* PSA calls to test: */
+
+    /* Creating SST asset "george," with data "@@002@10@@...". */
+    sst_status = psa_ps_set(@@@001@@@, george_data_size, george_data,
+                            PSA_STORAGE_FLAG_********);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+        return;
+    }
+
+    sst_status = psa_ps_remove(@@@001@@@);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("psa_ps_remove() expected PSA_SUCCESS.");
+        return;
+    }
+
+    sst_status = psa_ps_remove(@@@001@@@);
+    if (sst_status != PSA_ERROR_DOES_NOT_EXIST) {
+        TEST_FAIL("psa_ps_remove() expected PSA_ERROR_DOES_NOT_EXIST.");
+        return;
+    }
+
+
+    /* Removing assets left over from testing: */
+
+    /* Test completed */
+    ret->val = TEST_PASSED;
+}
diff --git a/tools/tf_fuzz/regression/000013_set_sst_name_rand_data_remove_twice/template b/tools/tf_fuzz/regression/000013_set_sst_name_rand_data_remove_twice/template
new file mode 100644
index 0000000..467ae6d
--- /dev/null
+++ b/tools/tf_fuzz/regression/000013_set_sst_name_rand_data_remove_twice/template
@@ -0,0 +1,4 @@
+purpose to illustrate deleting assets;
+set sst name george data *;
+remove sst name george;
+remove sst name george;
diff --git a/tools/tf_fuzz/regression/000014_set_sst_name_rand_data_remove_other/check.py b/tools/tf_fuzz/regression/000014_set_sst_name_rand_data_remove_other/check.py
new file mode 100644
index 0000000..a215e77
--- /dev/null
+++ b/tools/tf_fuzz/regression/000014_set_sst_name_rand_data_remove_other/check.py
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+import sys, os
+
+def main():
+    if len(sys.argv) != 4:
+        print >> sys.stderr, "%s requires 3 command-line arguments. Exiting." % sys.argv[0]
+        sys.exit(1)
+
+    #print "Command line args: %s" % (', '.join(sys.argv[1:4]))
+    sys.exit(0)
+
+if __name__ == "__main__":
+    main()
diff --git a/tools/tf_fuzz/regression/000014_set_sst_name_rand_data_remove_other/exp_stdout_stderr b/tools/tf_fuzz/regression/000014_set_sst_name_rand_data_remove_other/exp_stdout_stderr
new file mode 100644
index 0000000..25edad0
--- /dev/null
+++ b/tools/tf_fuzz/regression/000014_set_sst_name_rand_data_remove_other/exp_stdout_stderr
@@ -0,0 +1,24 @@
+Trusted Firmware Fuzzer (TF-Fuzz) starting...
+
+Info:  random seed was not specified.
+
+Using seed value of \d+ \(0x[a-f\d]+\).
+Purpose line:  to remove something that doesn't exist
+ASSET_IDENTIFIER:  "george"
+SST-asset identifier list:  "data"
+SST-create from random data
+Set SST command:  "*"
+Set command:  "*"
+Command with no expect:  ";"
+ASSET_IDENTIFIER:  "ringo"
+SST-asset identifier list:  ";"
+SST-remove arguments:  ";"
+Remove SST command:  ";"
+Remove command:  ";"
+Command with no expect:  ";"
+Lines:  Line number 4.
+Lines:  Line number 4.
+Lines:  Line number 4.
+Writing test file, test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tools/tf_fuzz/regression/000014_set_sst_name_rand_data_remove_other/exp_test.c b/tools/tf_fuzz/regression/000014_set_sst_name_rand_data_remove_other/exp_test.c
new file mode 100644
index 0000000..c66e70d
--- /dev/null
+++ b/tools/tf_fuzz/regression/000014_set_sst_name_rand_data_remove_other/exp_test.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/*
+ * Test purpose:
+ *     to remove something that doesn't exist
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "../sst/non_secure/ns_test_helpers.h"
+#include "psa/protected_storage.h"
+#include "test/framework/test_framework_helpers.h"
+#include "crypto_tests_common.h"
+#include "tfm_memory_utils.h"
+
+/* This is not yet right for how to run a test;  need to register tests, etc. */
+
+void test_thread (struct test_result_t *ret) {
+    psa_status_t crypto_status;  // result from Crypto calls
+    psa_status_t sst_status;
+
+    /* To prevent unused variable warning, as the variable might not be used
+     * in this testcase
+     */
+    (void)sst_status;
+
+    crypto_status = psa_crypto_init();
+    if (crypto_status != PSA_SUCCESS) {
+        TEST_FAIL("Could not initialize Crypto.");
+        return;
+    }
+
+    TEST_LOG("Test to remove something that doesn't exist");
+
+
+    /* Variables (etc.) to initialize and check PSA assets: */
+    static uint8_t george_data[] = "@@002@10@@********";
+    static int george_data_size = \d+;
+
+
+    /* PSA calls to test: */
+
+    /* Creating SST asset "george," with data "@@002@10@@...". */
+    sst_status = psa_ps_set(@@@001@@@, george_data_size, george_data,
+                            PSA_STORAGE_FLAG_********);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+        return;
+    }
+
+    sst_status = psa_ps_remove(********);
+    if (sst_status != PSA_ERROR_DOES_NOT_EXIST) {
+        TEST_FAIL("psa_ps_remove() expected PSA_ERROR_DOES_NOT_EXIST.");
+        return;
+    }
+
+    /* Removing assets left over from testing: */
+    psa_ps_remove(@@@001@@@);
+    if (sst_status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to tear down an SST asset upon test completion.");
+        return;
+    }
+
+    /* Test completed */
+    ret->val = TEST_PASSED;
+}
diff --git a/tools/tf_fuzz/regression/000014_set_sst_name_rand_data_remove_other/template b/tools/tf_fuzz/regression/000014_set_sst_name_rand_data_remove_other/template
new file mode 100644
index 0000000..5b9485c
--- /dev/null
+++ b/tools/tf_fuzz/regression/000014_set_sst_name_rand_data_remove_other/template
@@ -0,0 +1,3 @@
+purpose to remove something that doesn't exist;
+set sst name george data *;
+remove sst name ringo;
diff --git a/tools/tf_fuzz/regression/README b/tools/tf_fuzz/regression/README
new file mode 100644
index 0000000..d061dba
--- /dev/null
+++ b/tools/tf_fuzz/regression/README
@@ -0,0 +1,135 @@
+.../tf_fuzz/tf_fuzz_regression directory contents:
+
+ 000001_set_sst_uid_data_expect_pass
+ 000002_set_sst_name_data_expect_nothing
+ 000003_set_sst_name_data
+ 000004_set_sst_name_rand_data
+ 000005_set_sst_rand_name_rand_data
+ 000006_set_sst_multi_name_rand_data
+ 000007_set_sst_multi_uid_rand_data
+ 000008_set_sst_name_rand_data_read_check_wrong
+ 000009_set_sst_name_rand_data_read_check_var_read_print
+ 000010_read_nonexistent_sst_check_string
+ 000011_read_nonexistent_sst_check_string_expect_pass
+ 000012_read_nonexistent_sst_check_string_expect_other
+ 000013_set_sst_name_rand_data_remove_twice
+ 000014_set_sst_name_rand_data_remove_other
+ add_these_tests
+ README
+ regress
+ regress_lib
+
+--------------------------------------------------------------------------------
+
+This is the beginnings of a regression suite for TF-Fuzz.  That is, tests to
+make sure that tf_fuzz is still functioning properly after making changes.
+
+This is neither complete nor working yet, but is close to its first-pass
+implementation.
+
+Here's the basic scheme of it all:
+
+*  "bash regress" from this directory runs regression.  It will fail with an
+   error if a problem is found.  If it runs to completion, then regression has
+   passed.
+
+*  Each test is in its own sub-directory containing these files, by name (always
+   same name):
+
+  *  template:  The test-template file to be run though the TF-Fuzz under test,
+     here called "the DUT TF-Fuzz" here.
+
+  *  exp_stdout_stderr:  The *expected*, combined stdout and stderr from running
+     TF-Fuzz in verbose mode (-v).  This file contains wildcard expressions to
+     be checked (more on that below).
+
+  *  exp_test.c:  The *expected* output C code.  This file also contains
+     wildcard expressions to be resolved against the DUT TF-Fuzz output (again,
+     more on that below).
+
+  *  stdout_stderr (if present):  The combined stdout and stderr from running
+     the DUT TF-Fuzz in verbose mode (-v), during regression testing.
+
+  *  test.c (if present):  The output C code generated from running the DUT
+     TF-Fuzz in verbose mode (-v), during regression testing.
+
+  *  diff_stdout_stderr (if present):  The "diff" of stdout_stderr against
+     exp_stdout_stderr.  As mentioned above, there are wildcards in some lines
+     of exp_stdout_stderr that have to be resolved against stdout_stderr.
+
+  *  diff_test.c (if present):  The "diff" of test.c against exp_test.c.  As
+     mentioned above, there are wildcards in some lines of exp_test.c that have
+     to be resolved against test.c.
+
+  *  check.py:  This Python script doesn't yet, but will, resolve the wildcard
+     differences in diff_stdout_stderr and diff_test.c.  Each test directory
+     has its own script customized to the needs of that particular test, but
+     they all draw from functions in the regress_lib directory.
+
+To explain how check.py checks -- or will check! -- a regression test, consider
+one example of the ./000005_set_sst_rand_name_rand_data/diff_test.c file, below:
+
+    45,46c45,46
+    <     static uint8_t gibberish_data[] = "Gof jav ofdomviv wazauyicef zoc xut rus sekneiqiv eidzai yefrabxiyob abjie pah jashui ziuven qetuvraqwiu omwid xenmav fipwiy meftofc.";
+    <     int gibberish_data_size = 133;
+    ---
+    >     static uint8_t gibberish_data[] = "@@002@10@@********";
+    >     int gibberish_data_size = ********;
+    51,52c51,52
+    <     /* Creating SST asset "gibberish," with data "Gof jav of...". */
+    <     sst_status = psa_ps_set(8617, gibberish_data_size, gibberish_data, PSA_PS_FLAG_NONE);
+    ---
+    >     /* Creating SST asset "gibberish," with data "@@002@10@@...". */
+    >     sst_status = psa_ps_set(@@@001@@@, gibberish_data_size, gibberish_data, PSA_PS_FLAG_********);
+    60c60
+    <     psa_ps_remove(8617);
+    ---
+    >     psa_ps_remove(@@@001@@@);
+
+So, by this process, a simple "diff" itself checks the vast majority of the
+correctness of the result.  check.py has only to resolve the wildcards, and in
+the process will also immediately see cases where "diff" discovered disparities.
+
+The wildcards in the exp_stdout_stderr and exp_test.c files are of three basic
+natures, using the examples shown above (please reference them above to
+clearly understand the ideas here):
+
+  ******** (exactly 8 *s):
+      This denotes any pattern of characters, until the expected and actual
+      character streams re-converge (sync up) again.  The characters in the
+      output from stdout_stderr or test.c from the DUT TF-Fuzz, that
+      correspond to the ******** in the exp_stdout_stderr or exp_test.c files
+      are *not* checked;  anything in the output from the DUT TF-Fuzz at this
+      position is acceptable.
+
+  @@@001@@@ ("@@@", a pattern number, "@@@"):
+      This denotes a particular pattern of characters, until the expected and
+      actual character streams re-sync again.  The important thing, however,
+      is that what this wildcard stands for *must be consistent* throughout the
+      comparison!  In this case above, @@@001@@@ in the exp_test.c must consis-
+      tently correspond to "8617" everywhere throughout the test.c file.  The
+      number between the two "@@@"s in the wildcard designates which pattern
+      must consistently match.
+
+  @@002@10@@ ("@@", a pattern number, "@", a pattern size, "@@"):
+      This is a slight variant upon the previous wildcard, in which a specific
+      match length is required.  In lines 45 and 46 above, random data generated
+      consists of 10 characters (thus the ...@10@@ in the wildcard) "Gof jav of"
+      followed by other characters we don't care about;  they can be anything.
+      Thus "@@002@10@@********" in line 45 of exp_test.c:  the "@@002@10@@"
+      denotes a pattern number 002 for a length of 10 characters that must match
+      "Gof jav of" in this case, followed by some arbitrary number of characters
+      we don't care about, thus ******** in exp_test.c, line 45.
+
+After the check.py capability -- resolving these wildcards -- for this purpose
+is fleshed out, we shall have to figure out how to address "shuffle" and
+"2 to 5 of {}" randomizations.
+
+--------------------------------------------------------------------------------
+
+The add_these_tests directory contains regression-test information of the above
+nature that the regression framework is not currently able to address.
+
+--------------
+
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
diff --git a/tools/tf_fuzz/regression/add_these_tests/000015_set_sst_multi_name_remove_rand_active/exp_stdout_stderr b/tools/tf_fuzz/regression/add_these_tests/000015_set_sst_multi_name_remove_rand_active/exp_stdout_stderr
new file mode 100644
index 0000000..6bfbee2
--- /dev/null
+++ b/tools/tf_fuzz/regression/add_these_tests/000015_set_sst_multi_name_remove_rand_active/exp_stdout_stderr
@@ -0,0 +1,28 @@
+Trusted Firmware Fuzzer (TF-Fuzz) starting...
+
+Info:  random seed was not specified.
+
+Using seed value of \d+ \(0x[a-f\d]+\).
+Purpose line:  to show a more-interesting removal case
+ASSET_IDENTIFIER:  "president"
+ASSET_IDENTIFIER:  "george"
+ASSET_IDENTIFIER:  "herbert"
+ASSET_IDENTIFIER:  "walker"
+ASSET_IDENTIFIER:  "bush"
+SST-asset identifier list:  "data"
+LITERAL:  "read my lips"
+SST-create from literal data:  ""read my lips""
+Set SST command:  ""read my lips""
+Set command:  ""read my lips""
+Command with no expect:  ";"
+SST-asset random active:  "active"
+SST-remove arguments:  "active"
+Remove SST command:  "active"
+Remove command:  "active"
+Command with no expect:  ";"
+Lines:  Line number 4.
+Lines:  Line number 4.
+Lines:  Line number 4.
+Writing test file, test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tools/tf_fuzz/regression/add_these_tests/000015_set_sst_multi_name_remove_rand_active/exp_test.c b/tools/tf_fuzz/regression/add_these_tests/000015_set_sst_multi_name_remove_rand_active/exp_test.c
new file mode 100644
index 0000000..2d6e9e8
--- /dev/null
+++ b/tools/tf_fuzz/regression/add_these_tests/000015_set_sst_multi_name_remove_rand_active/exp_test.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/*
+ * Test purpose:
+ *     to show a more-interesting removal case
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "../sst/non_secure/ns_test_helpers.h"
+#include "psa/protected_storage.h"
+#include "test/framework/test_framework_helpers.h"
+#include "crypto_tests_common.h"
+#include "tfm_memory_utils.h"
+/* For now, just a single test_result_t struct is sufficient.*/
+static struct test_result_t ret;
+
+/* This is not yet right for how to run a test;  need to register tests, etc. */
+
+void test_thread (struct test_result_t *ret) {
+    psa_status_t crypto_status;  // result from Crypto calls
+    psa_ps_status_t sst_status;
+
+    crypto_status = psa_crypto_init();
+    if (crypto_status != PSA_SUCCESS) {
+        TEST_FAIL("Could not initialize Crypto.");
+        return;
+    }
+
+    TEST_LOG("Test to show a more-interesting removal case");
+
+
+    /* Variables (etc.) to initialize and check PSA assets: */
+    static uint8_t president_data[] = "read my lips";
+    int president_data_size = 12;
+    static uint8_t george_data[] = "read my lips";
+    int george_data_size = 12;
+    static uint8_t herbert_data[] = "read my lips";
+    int herbert_data_size = 12;
+    static uint8_t walker_data[] = "read my lips";
+    int walker_data_size = 12;
+    static uint8_t bush_data[] = "read my lips";
+    int bush_data_size = 12;
+
+
+    /* PSA calls to test: */
+
+    /* Creating SST asset "president," with data "read my li...". */
+    sst_status = psa_ps_set(@@@001@@@, president_data_size, president_data, PSA_PS_FLAG_WRITE_ONCE);
+    if (sst_status != PSA_PS_SUCCESS) {
+        TEST_FAIL("psa_ps_set() expected PSA_PS_SUCCESS, got #%d, (int) sst_status);
+        return;
+    }
+
+    /* Creating SST asset "george," with data "read my li...". */
+    sst_status = psa_ps_set(5517, george_data_size, george_data, PSA_PS_FLAG_WRITE_ONCE);
+    if (sst_status != PSA_PS_SUCCESS) {
+        TEST_FAIL("psa_ps_set() expected PSA_PS_SUCCESS, got #%d, (int) sst_status);
+        return;
+    }
+
+    /* Creating SST asset "herbert," with data "read my li...". */
+    sst_status = psa_ps_set(4661, herbert_data_size, herbert_data, PSA_PS_FLAG_WRITE_ONCE);
+    if (sst_status != PSA_PS_SUCCESS) {
+        TEST_FAIL("psa_ps_set() expected PSA_PS_SUCCESS, got #%d, (int) sst_status);
+        return;
+    }
+
+    /* Creating SST asset "walker," with data "read my li...". */
+    sst_status = psa_ps_set(3441, walker_data_size, walker_data, PSA_PS_FLAG_WRITE_ONCE);
+    if (sst_status != PSA_PS_SUCCESS) {
+        TEST_FAIL("psa_ps_set() expected PSA_PS_SUCCESS, got #%d, (int) sst_status);
+        return;
+    }
+
+    /* Creating SST asset "bush," with data "read my li...". */
+    sst_status = psa_ps_set(5446, bush_data_size, bush_data, PSA_PS_FLAG_WRITE_ONCE);
+    if (sst_status != PSA_PS_SUCCESS) {
+        TEST_FAIL("psa_ps_set() expected PSA_PS_SUCCESS, got #%d, (int) sst_status);
+        return;
+    }
+
+    sst_status = psa_ps_remove(5517);
+    if (sst_status != PSA_PS_SUCCESS) {
+        TEST_FAIL("psa_ps_remove() expected PSA_PS_SUCCESS, got #%d", (int) sst_status);
+    }
+
+
+    /* Removing assets left over from testing: */
+    psa_ps_remove(@@@001@@@);
+    if (sst_status != PSA_PS_SUCCESS) {
+        TEST_FAIL("Failed to tear down an SST asset upon test completion!");
+        return;
+    }
+    psa_ps_remove(4661);
+    if (sst_status != PSA_PS_SUCCESS) {
+        TEST_FAIL("Failed to tear down an SST asset upon test completion!");
+        return;
+    }
+    psa_ps_remove(3441);
+    if (sst_status != PSA_PS_SUCCESS) {
+        TEST_FAIL("Failed to tear down an SST asset upon test completion!");
+        return;
+    }
+    psa_ps_remove(5446);
+    if (sst_status != PSA_PS_SUCCESS) {
+        TEST_FAIL("Failed to tear down an SST asset upon test completion!");
+        return;
+    }
+
+    /* Test completed */
+    ret->val = TEST_PASSED;
+}
diff --git a/tools/tf_fuzz/regression/add_these_tests/000015_set_sst_multi_name_remove_rand_active/template b/tools/tf_fuzz/regression/add_these_tests/000015_set_sst_multi_name_remove_rand_active/template
new file mode 100644
index 0000000..613439e
--- /dev/null
+++ b/tools/tf_fuzz/regression/add_these_tests/000015_set_sst_multi_name_remove_rand_active/template
@@ -0,0 +1,3 @@
+purpose to show a more-interesting removal case;
+set sst name president george herbert walker bush data "read my lips";
+remove sst *active;  // remove *some* active asset
diff --git a/tools/tf_fuzz/regression/add_these_tests/000016_set_sst_multi_name_remove_multi_rand_active_remove_rand_deleted/exp_stdout_stderr b/tools/tf_fuzz/regression/add_these_tests/000016_set_sst_multi_name_remove_multi_rand_active_remove_rand_deleted/exp_stdout_stderr
new file mode 100644
index 0000000..fea4857
--- /dev/null
+++ b/tools/tf_fuzz/regression/add_these_tests/000016_set_sst_multi_name_remove_multi_rand_active_remove_rand_deleted/exp_stdout_stderr
@@ -0,0 +1,46 @@
+Trusted Firmware Fuzzer (TF-Fuzz) starting...
+
+Info:  random seed was not specified.
+
+Using seed value of \d+ \(0x[a-f\d]+\).
+Purpose line:  to show a more-interesting removal case
+ASSET_IDENTIFIER:  "president"
+ASSET_IDENTIFIER:  "george"
+ASSET_IDENTIFIER:  "herbert"
+ASSET_IDENTIFIER:  "walker"
+ASSET_IDENTIFIER:  "bush"
+SST-asset identifier list:  "data"
+LITERAL:  "no new taxes"
+SST-create from literal data:  ""no new taxes""
+Set SST command:  ""no new taxes""
+Set command:  ""no new taxes""
+Command with no expect:  ";"
+SST-asset random active:  "active"
+SST-remove arguments:  "active"
+Remove SST command:  "active"
+Remove command:  "active"
+Command with no expect:  ";"
+SST-asset random active:  "active"
+SST-remove arguments:  "active"
+Remove SST command:  "active"
+Remove command:  "active"
+Command with no expect:  ";"
+SST-asset random active:  "active"
+SST-remove arguments:  "active"
+Remove SST command:  "active"
+Remove command:  "active"
+Command with no expect:  ";"
+SST-asset random deleted:  "deleted"
+SST-remove arguments:  "deleted"
+Remove SST command:  "deleted"
+Remove command:  "deleted"
+Command with no expect:  ";"
+Lines:  Line number 7.
+Lines:  Line number 7.
+Lines:  Line number 7.
+Lines:  Line number 7.
+Lines:  Line number 7.
+Lines:  Line number 7.
+Writing test file, test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tools/tf_fuzz/regression/add_these_tests/000016_set_sst_multi_name_remove_multi_rand_active_remove_rand_deleted/exp_test.c b/tools/tf_fuzz/regression/add_these_tests/000016_set_sst_multi_name_remove_multi_rand_active_remove_rand_deleted/exp_test.c
new file mode 100644
index 0000000..c4ac4f3
--- /dev/null
+++ b/tools/tf_fuzz/regression/add_these_tests/000016_set_sst_multi_name_remove_multi_rand_active_remove_rand_deleted/exp_test.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/*
+ * Test purpose:
+ *     to show a more-interesting removal case
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "../sst/non_secure/ns_test_helpers.h"
+#include "psa/protected_storage.h"
+#include "test/framework/test_framework_helpers.h"
+#include "crypto_tests_common.h"
+#include "tfm_memory_utils.h"
+/* For now, just a single test_result_t struct is sufficient.*/
+static struct test_result_t ret;
+
+/* This is not yet right for how to run a test;  need to register tests, etc. */
+
+void test_thread (struct test_result_t *ret) {
+    psa_status_t crypto_status;  // result from Crypto calls
+    psa_ps_status_t sst_status;
+
+    crypto_status = psa_crypto_init();
+    if (crypto_status != PSA_SUCCESS) {
+        TEST_FAIL("Could not initialize Crypto.");
+        return;
+    }
+
+    TEST_LOG("Test to show a more-interesting removal case");
+
+
+    /* Variables (etc.) to initialize and check PSA assets: */
+    static uint8_t president_data[] = "no new taxes";
+    int president_data_size = 12;
+    static uint8_t george_data[] = "no new taxes";
+    int george_data_size = 12;
+    static uint8_t herbert_data[] = "no new taxes";
+    int herbert_data_size = 12;
+    static uint8_t walker_data[] = "no new taxes";
+    int walker_data_size = 12;
+    static uint8_t bush_data[] = "no new taxes";
+    int bush_data_size = 12;
+
+
+    /* PSA calls to test: */
+
+    /* Creating SST asset "president," with data "no new tax...". */
+    sst_status = psa_ps_set(4713, president_data_size, president_data,
+                            PSA_PS_FLAG_WRITE_ONCE);
+    if (sst_status != PSA_PS_SUCCESS) {
+        TEST_FAIL("psa_ps_set() expected PSA_PS_SUCCESS, got #%d, (int) sst_status);
+        return;
+    }
+
+    /* Creating SST asset "george," with data "no new tax...". */
+    sst_status = psa_ps_set(5517, george_data_size, george_data, PSA_PS_FLAG_WRITE_ONCE);
+    if (sst_status != PSA_PS_SUCCESS) {
+        TEST_FAIL("psa_ps_set() expected PSA_PS_SUCCESS, got #%d, (int) sst_status);
+        return;
+    }
+
+    /* Creating SST asset "herbert," with data "no new tax...". */
+    sst_status = psa_ps_set(4661, herbert_data_size, herbert_data, PSA_PS_FLAG_WRITE_ONCE);
+    if (sst_status != PSA_PS_SUCCESS) {
+        TEST_FAIL("psa_ps_set() expected PSA_PS_SUCCESS, got #%d, (int) sst_status);
+        return;
+    }
+
+    /* Creating SST asset "walker," with data "no new tax...". */
+    sst_status = psa_ps_set(3441, walker_data_size, walker_data, PSA_PS_FLAG_WRITE_ONCE);
+    if (sst_status != PSA_PS_SUCCESS) {
+        TEST_FAIL("psa_ps_set() expected PSA_PS_SUCCESS, got #%d, (int) sst_status);
+        return;
+    }
+
+    /* Creating SST asset "bush," with data "no new tax...". */
+    sst_status = psa_ps_set(5446, bush_data_size, bush_data, PSA_PS_FLAG_WRITE_ONCE);
+    if (sst_status != PSA_PS_SUCCESS) {
+        TEST_FAIL("psa_ps_set() expected PSA_PS_SUCCESS, got #%d, (int) sst_status);
+        return;
+    }
+
+    sst_status = psa_ps_remove(5517);
+    if (sst_status != PSA_PS_SUCCESS) {
+        TEST_FAIL("psa_ps_remove() expected PSA_PS_SUCCESS, got #%d", (int) sst_status);
+    }
+
+    sst_status = psa_ps_remove(4713);
+    if (sst_status != PSA_PS_SUCCESS) {
+        TEST_FAIL("psa_ps_remove() expected PSA_PS_SUCCESS, got #%d", (int) sst_status);
+    }
+
+    sst_status = psa_ps_remove(3441);
+    if (sst_status != PSA_PS_SUCCESS) {
+        TEST_FAIL("psa_ps_remove() expected PSA_PS_SUCCESS, got #%d", (int) sst_status);
+    }
+
+    sst_status = psa_ps_remove(3441);
+    if (sst_status != PSA_PS_ERROR_UID_NOT_FOUND) {
+        TEST_FAIL("psa_ps_remove() expected PSA_PS_ERROR_UID_NOT_FOUND, got #%d", (int) sst_status);
+    }
+
+
+    /* Removing assets left over from testing: */
+    psa_ps_remove(4661);
+    if (sst_status != PSA_PS_SUCCESS) {
+        TEST_FAIL("Failed to tear down an SST asset upon test completion!");
+        return;
+    }
+    psa_ps_remove(5446);
+    if (sst_status != PSA_PS_SUCCESS) {
+        TEST_FAIL("Failed to tear down an SST asset upon test completion!");
+        return;
+    }
+
+    /* Test completed */
+    ret->val = TEST_PASSED;
+}
diff --git a/tools/tf_fuzz/regression/add_these_tests/000016_set_sst_multi_name_remove_multi_rand_active_remove_rand_deleted/template b/tools/tf_fuzz/regression/add_these_tests/000016_set_sst_multi_name_remove_multi_rand_active_remove_rand_deleted/template
new file mode 100644
index 0000000..e7a21b3
--- /dev/null
+++ b/tools/tf_fuzz/regression/add_these_tests/000016_set_sst_multi_name_remove_multi_rand_active_remove_rand_deleted/template
@@ -0,0 +1,6 @@
+purpose to show a more-interesting removal case;
+set sst name president george herbert walker bush data "no new taxes";
+remove sst *active;  // remove *some* active asset
+remove sst *active;  // remove *some other* active asset
+remove sst *active;  // remove *yet another* active asset
+remove sst *deleted;  // attempt to remove some asset that's already been removed
diff --git a/tools/tf_fuzz/regression/regress b/tools/tf_fuzz/regression/regress
new file mode 100644
index 0000000..ff51ba2
--- /dev/null
+++ b/tools/tf_fuzz/regression/regress
@@ -0,0 +1,18 @@
+# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+echo
+echo TF-Fuzz Regression Testing
+echo
+for reg_test in `ls -F | grep \/$ | grep -v add_these_tests | grep -v regress_lib`; do
+    echo Running "$reg_test"...
+    cd $reg_test
+    rm -f test.c stdout_stderr
+    ../../tfz -v ./template test.c >stdout_stderr 2>&1
+    rm -f diff_stdout_stderr diff_test.c
+    diff stdout_stderr exp_stdout_stderr >diff_stdout_stderr
+    diff test.c exp_test.c >diff_test.c
+    python ./check.py diff_stdout_stderr diff_test.c stdout_stderr
+    cd ..
+done
diff --git a/tools/tf_fuzz/template/README b/tools/tf_fuzz/template/README
new file mode 100644
index 0000000..0d76e54
--- /dev/null
+++ b/tools/tf_fuzz/template/README
@@ -0,0 +1,14 @@
+.../tf_fuzz/template directory contents:
+
+crypto_template_line.cpp  secure_template_line.hpp  template_line.cpp
+crypto_template_line.hpp  sst_template_line.cpp     template_line.hpp
+secure_template_line.cpp  sst_template_line.hpp
+
+--------------------------------------------------------------------------------
+
+These classes describe "tracker" objects for parsing test templates, and for
+generating PSA calls from them.
+
+--------------
+
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
diff --git a/tools/tf_fuzz/template/crypto_template_line.cpp b/tools/tf_fuzz/template/crypto_template_line.cpp
new file mode 100644
index 0000000..8a1333b
--- /dev/null
+++ b/tools/tf_fuzz/template/crypto_template_line.cpp
@@ -0,0 +1,353 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "class_forwards.hpp"
+
+#include "boilerplate.hpp"
+#include "gibberish.hpp"
+#include "compute.hpp"
+#include "data_blocks.hpp"
+#include "psa_asset.hpp"
+#include "find_or_create_asset.hpp"
+#include "template_line.hpp"
+#include "tf_fuzz.hpp"
+#include "crypto_asset.hpp"
+#include "psa_call.hpp"
+#include "crypto_call.hpp"
+#include "sst_asset.hpp"
+#include "crypto_asset.hpp"
+#include "crypto_template_line.hpp"
+
+
+
+/**********************************************************************************
+   Methods of class set_policy_template_line follow:
+**********************************************************************************/
+
+set_policy_template_line::set_policy_template_line (tf_fuzz_info *resources)
+    : policy_template_line (resources)
+{
+    // No further setup to be performed.
+    return;  // just to have something to pin a breakpoint onto
+}
+
+bool set_policy_template_line::copy_template_to_asset (void)
+{
+    // TODO:  Should this ever be invoked?
+    return true;
+}
+
+bool set_policy_template_line::copy_template_to_call (void)
+{
+    for (auto call : test_state->calls) {
+        if (call->call_ser_no == call_ser_no && call->expect.pf_info_incomplete) {
+            call->asset_id.set_just_name (asset_id.get_name());
+            call->asset_id.id_n = asset_id.id_n;
+            call->expect.pf_info_incomplete = true;
+            return true;
+        }
+    }
+    return false;  // failed to find the call
+}
+
+// Default destructor:
+set_policy_template_line::~set_policy_template_line (void)
+{
+    // TODO:  Add an error for this being invoked.
+    return;  // just to have something to pin a breakpoint onto
+}
+
+// (Default constructor not used)
+
+
+/**********************************************************************************
+   End of methods of class set_policy_template_line.
+**********************************************************************************/
+
+
+/**********************************************************************************
+   Methods of class read_policy_template_line follow:
+**********************************************************************************/
+
+read_policy_template_line::read_policy_template_line (tf_fuzz_info *resources)
+    : policy_template_line (resources)
+{
+}
+
+bool read_policy_template_line::copy_template_to_asset (void)
+{
+    vector<psa_asset*>::iterator found_asset;
+    sst_asset* this_asset;
+    // Find the call by serial number (must search;  may have moved).
+    asset_search how_found = test_state->find_or_create_sst_asset (
+                        psa_asset_search::serial, psa_asset_usage::all, "", 0,
+                        asset_ser_no, dont_create_asset, found_asset );
+    // The vector is base-class, but this itself *really is* an sst_asset object:
+    if (how_found == asset_search::unsuccessful) {
+        cerr << "\nError:  Tool-internal:  TF-Fuzz failed to find a required asset."
+             << endl;
+        exit(108);
+    }
+    // Copy *the other way* on asset reads!
+    if (how_found != asset_search::not_found) {
+        this_asset = reinterpret_cast<sst_asset*>(*found_asset);
+        set_data.string_specified = this_asset->set_data.string_specified;
+        set_data.file_specified = this_asset->set_data.file_specified;
+        flags_string = this_asset->flags_string;
+        asset_id.id_n = this_asset->asset_id.id_n;
+        asset_id.name_specified = this_asset->asset_id.name_specified;
+    }
+    return true;
+}
+
+bool read_policy_template_line::copy_template_to_call (void)
+{
+    for (auto call : test_state->calls) {
+        if (call->call_ser_no == call_ser_no && call->expect.pf_info_incomplete) {
+            call->asset_id.set_just_name (asset_id.get_name());
+            call->asset_id.id_n = asset_id.id_n;
+            call->expect.pf_info_incomplete = true;
+            return true;
+        }
+    }
+    return false;  // failed to find the call
+}
+
+// Default destructor:
+read_policy_template_line::~read_policy_template_line (void)
+{
+    return;  // just to have something to pin a breakpoint onto
+}
+
+// (Default constructor not used)
+
+
+/**********************************************************************************
+   End of methods of class read_policy_template_line.
+**********************************************************************************/
+
+
+/**********************************************************************************
+   Methods of class set_key_template_line follow:
+**********************************************************************************/
+
+set_key_template_line::set_key_template_line (tf_fuzz_info *resources)
+    : key_template_line (resources)
+{
+    // Nothing further to initialize.
+}
+
+bool set_key_template_line::copy_template_to_asset (void)
+{
+    vector<psa_asset*>::iterator found_asset;
+    key_asset* this_asset;
+
+    // Find the asset by serial number (must search;  may have moved).
+    asset_search how_found = test_state->find_or_create_key_asset (
+                        psa_asset_search::serial, psa_asset_usage::all, "", 0,
+                        asset_ser_no, yes_create_asset, found_asset );
+    // The vector is base-class, but this itself *really is* a key_asset object:
+    if (how_found == asset_search::unsuccessful) {
+        cerr << "\nError:  Tool-internal:  TF-Fuzz failed to find a required asset."
+             << endl;
+        exit(109);
+    }
+    // Copy over everything relevant:
+    if (how_found != asset_search::not_found) {  // will be found for make calls, but not necessarily others
+        this_asset = reinterpret_cast<key_asset*>(*found_asset);
+        this_asset->set_data.string_specified = set_data.string_specified;
+        this_asset->set_data.set (set_data.get());
+        this_asset->set_data.file_specified = set_data.file_specified;
+        this_asset->set_data.file_path = set_data.file_path;
+        this_asset->flags_string = flags_string;
+    }
+    return true;
+}
+
+bool set_key_template_line::copy_template_to_call (void)
+{
+    // Find the call by serial number (must search;  may have moved).
+    for (auto call : test_state->calls) {
+        if (call->call_ser_no == call_ser_no) {
+            // Copy asset info to call object for creation code:
+            call->asset_id.set_just_name (asset_id.get_name());
+            call->asset_id.id_n = asset_id.id_n;
+            call->set_data.string_specified = set_data.string_specified;
+            call->set_data.set (set_data.get());  call->asset_ser_no = asset_ser_no;
+            call->set_data.file_specified = set_data.file_specified;
+            call->set_data.file_path = set_data.file_path;
+            call->flags_string = flags_string;
+            call->how_asset_found = how_asset_found;
+            call->expect.pf_info_incomplete = true;
+            return true;
+        }
+    }
+    return false;  // somehow didn't find it the call.
+}
+
+// Default destructor:
+set_key_template_line::~set_key_template_line (void)
+{
+    return;  // just to have something to pin a breakpoint onto
+}
+
+// (Default constructor not used)
+
+
+/**********************************************************************************
+   End of methods of class set_key_template_line.
+**********************************************************************************/
+
+
+/**********************************************************************************
+   Methods of class remove_key_template_line follow:
+**********************************************************************************/
+
+remove_key_template_line::remove_key_template_line (tf_fuzz_info *resources)
+    : key_template_line (resources)
+{
+    is_remove = true;  // template_line's constructor defaults this to false
+}
+
+bool remove_key_template_line::copy_template_to_asset (void)
+{
+    vector<psa_asset*>::iterator found_asset;
+    sst_asset* this_asset;
+    // Find the call by serial number (must search;  may have moved).
+    asset_search how_found = test_state->find_or_create_sst_asset (
+                        psa_asset_search::serial, psa_asset_usage::all, "", 0,
+                        asset_ser_no, dont_create_asset, found_asset );
+    // The vector is base-class, but this itself *really is* an sst_asset object:
+    if (how_found == asset_search::unsuccessful) {
+        cerr << "\nError:  Tool-internal:  TF-Fuzz failed to find a required asset."
+             << endl;
+        exit(108);
+    }
+    // Copy *the other way* on asset reads!
+    if (how_found != asset_search::not_found) {  // will be found for make calls, but not necessarily others
+        this_asset = reinterpret_cast<sst_asset*>(*found_asset);
+        set_data.string_specified = this_asset->set_data.string_specified;
+        set_data.file_specified = this_asset->set_data.file_specified;
+        flags_string = this_asset->flags_string;
+        asset_id.id_n = this_asset->asset_id.id_n;
+        asset_id.name_specified = this_asset->asset_id.name_specified;
+    }
+    return true;
+}
+
+bool remove_key_template_line::copy_template_to_call (void)
+{
+    // Find the call by serial number (must search;  may have moved).
+    for (auto call : test_state->calls) {
+        if (call->call_ser_no == call_ser_no) {
+            call->asset_id.set_just_name (asset_id.get_name());
+            call->asset_id.id_n = asset_id.id_n;
+            call->expect.pf_nothing = expect.pf_nothing;
+            call->expect.pf_pass = expect.pf_pass;  call->asset_ser_no = asset_ser_no;
+            call->expect.pf_specified = expect.pf_specified;
+            call->expect.pf_result_string = expect.pf_result_string;
+            call->how_asset_found = how_asset_found;
+            call->expect.pf_info_incomplete = true;
+            return true;
+        }
+    }
+    return false;  // somehow didn't find it the call.
+}
+
+// Default destructor:
+remove_key_template_line::~remove_key_template_line (void)
+{
+    return;  // just to have something to pin a breakpoint onto
+}
+
+// (Default constructor not used)
+
+
+/**********************************************************************************
+   End of methods of class remove_key_template_line.
+**********************************************************************************/
+
+
+/**********************************************************************************
+   Methods of class read_key_template_line follow:
+**********************************************************************************/
+
+read_key_template_line::read_key_template_line (tf_fuzz_info *resources)
+    : key_template_line (resources)
+{
+    char gibberish_buffer[4096];  string databuff;
+    int data_length;
+    set_data.string_specified = (rand()%2) == 1?  true : false;
+
+    // Go ahead and create a literal-data string even if not ultimately used:
+    data_length = test_state->gibbergen.pick_sentence_len();
+    test_state->gibbergen.sentence (gibberish_buffer, gibberish_buffer + data_length);
+    databuff = gibberish_buffer;  set_data.set (databuff);
+
+    set_data.file_specified = (!set_data.string_specified && (rand()%2) == 1)?  true : false;
+    set_data.file_path = "";  // can't really devise a random path
+}
+
+bool read_key_template_line::copy_template_to_asset (void)
+{
+    vector<psa_asset*>::iterator found_asset;
+    sst_asset* this_asset;
+    // Find the call by serial number (must search;  may have moved).
+    asset_search how_found = test_state->find_or_create_sst_asset (
+                        psa_asset_search::serial, psa_asset_usage::all, "", 0,
+                        asset_ser_no, dont_create_asset, found_asset );
+    // The vector is base-class, but this itself *really is* an sst_asset object:
+    if (how_found == asset_search::unsuccessful) {
+        cerr << "\nError:  Tool-internal:  TF-Fuzz failed to find a required asset."
+             << endl;
+        exit(108);
+    }
+    // Copy *the other way* on asset reads!
+    if (how_found != asset_search::not_found) {
+        this_asset = reinterpret_cast<sst_asset*>(*found_asset);
+        set_data.string_specified = this_asset->set_data.string_specified;
+        set_data.file_specified = this_asset->set_data.file_specified;
+        flags_string = this_asset->flags_string;
+        asset_id.id_n = this_asset->asset_id.id_n;
+        asset_id.name_specified = this_asset->asset_id.name_specified;
+    }
+    return true;
+}
+
+bool read_key_template_line::copy_template_to_call (void)
+{
+    // Find the call by serial number (must search;  may have moved).
+    for (auto call : test_state->calls) {
+        if (call->call_ser_no == call_ser_no) {
+            // Copy expected results to the call object, to check:
+            call->asset_id.set_just_name (asset_id.get_name());
+            call->asset_id.id_n = asset_id.id_n;
+            call->set_data.string_specified = set_data.string_specified;
+            call->set_data.set (set_data.get());  call->asset_ser_no = asset_ser_no;
+            call->set_data.file_specified = set_data.file_specified;
+            call->set_data.file_path = set_data.file_path;
+            call->flags_string = flags_string;
+            call->set_data.string_specified = set_data.string_specified;
+            call->how_asset_found = how_asset_found;
+            call->expect.pf_info_incomplete = true;
+            return true;
+        }
+    }
+    return false;  // somehow didn't find it the call.
+}
+
+// Default destructor:
+read_key_template_line::~read_key_template_line (void)
+{
+    return;  // just to have something to pin a breakpoint onto
+}
+
+// (Default constructor not used)
+
+/**********************************************************************************
+   End of methods of class read_key_template_line.
+**********************************************************************************/
diff --git a/tools/tf_fuzz/template/crypto_template_line.hpp b/tools/tf_fuzz/template/crypto_template_line.hpp
new file mode 100644
index 0000000..f79b0fd
--- /dev/null
+++ b/tools/tf_fuzz/template/crypto_template_line.hpp
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef CRYPTO_TEMPLATE_LINE_HPP
+#define CRYPTO_TEMPLATE_LINE_HPP
+
+#include <cstdint>
+
+/* This project's header files #including other project headers quickly becomes
+   unrealistically complicated.  The only solution is for each .cpp to include
+   the headers it needs.
+#include "psa_asset.hpp"
+//class psa_asset;  // just need a forward reference
+#include "template_line.hpp"
+#include "psa_call.hpp"
+*/
+using namespace std;
+
+
+class set_policy_template_line : public policy_template_line
+{
+public:
+    // Data members:
+    // Methods:
+        bool copy_template_to_asset (void);
+        bool copy_template_to_call (void);
+        void setup_call (set_data_info set_info, bool random_data,
+                            bool fill_in_template, bool create_call,
+                            template_line *temLin, tf_fuzz_info *rsrc) {
+            define_call<policy_set_call> (set_data, random_data,
+                            fill_in_template, create_call, temLin, rsrc);
+        }
+        set_policy_template_line (tf_fuzz_info *resources);  // (constructor)
+        ~set_policy_template_line (void);
+
+protected:
+    // Data members:
+    // Methods:
+
+private:
+    // Data members:
+    // Methods:
+};
+
+
+class read_policy_template_line : public policy_template_line
+{
+public:
+    // Data members:
+    // Methods:
+        bool copy_template_to_asset (void);
+        bool copy_template_to_call (void);
+        void setup_call (set_data_info set_info, bool random_data,
+                            bool fill_in_template, bool create_call,
+                            template_line *temLin, tf_fuzz_info *rsrc) {
+            define_call<policy_get_call> (set_data, random_data,
+                            fill_in_template, create_call, temLin, rsrc);
+        }
+        read_policy_template_line (tf_fuzz_info *resources);  // (constructor)
+        ~read_policy_template_line (void);
+
+protected:
+    // Data members:
+    // Methods:
+
+private:
+    // Data members:
+    // Methods:
+};
+
+
+class set_key_template_line : public key_template_line
+{
+public:
+   // Data members:
+    // Methods:
+        bool copy_template_to_asset (void);
+        bool copy_template_to_call (void);
+        void setup_call (set_data_info set_info, bool random_data,
+                         bool fill_in_template, bool create_call,
+                         template_line *temLin, tf_fuzz_info *rsrc) {
+            define_call<set_key_call> (set_info, random_data,
+                            fill_in_template, create_call, temLin, rsrc);
+        }
+        set_key_template_line (tf_fuzz_info *resources);  // (constructor)
+        ~set_key_template_line (void);
+
+protected:
+    // Data members:
+    // Methods:
+
+private:
+    // Data members:
+    // Methods:
+};
+
+class remove_key_template_line : public key_template_line
+{
+public:
+    // Data members:
+    // Methods:
+        bool copy_template_to_asset (void);
+        bool copy_template_to_call (void);
+        void setup_call (set_data_info set_info, bool random_data,
+                         bool fill_in_template, bool create_call,
+                         template_line *temLin, tf_fuzz_info *rsrc) {
+            define_call<destroy_key_call> (set_data, random_data,
+                            fill_in_template, create_call, temLin, rsrc);
+        }
+        remove_key_template_line (tf_fuzz_info *resources);  // (constructor)
+        ~remove_key_template_line (void);
+
+protected:
+    // Data members:
+    // Methods:
+
+private:
+    // Data members:
+    // Methods:
+};
+
+class read_key_template_line : public key_template_line
+{
+public:
+    // Data members:
+    // Methods:
+        bool copy_template_to_asset (void);
+        bool copy_template_to_call (void);
+        void setup_call (set_data_info set_info, bool random_data,
+                         bool fill_in_template, bool create_call,
+                         template_line *temLin, tf_fuzz_info *rsrc) {
+            define_call<get_key_info_call> (set_data, random_data,
+                            fill_in_template, create_call, temLin, rsrc);
+        }
+        read_key_template_line (tf_fuzz_info *resources);  // (constructor)
+        ~read_key_template_line (void);
+
+protected:
+    // Data members:
+    // Methods:
+
+private:
+    // Data members:
+    // Methods:
+};
+
+#endif  // #ifndef CRYPTO_TEMPLATE_LINE_HPP
diff --git a/tools/tf_fuzz/template/secure_template_line.cpp b/tools/tf_fuzz/template/secure_template_line.cpp
new file mode 100644
index 0000000..0cf88e8
--- /dev/null
+++ b/tools/tf_fuzz/template/secure_template_line.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "class_forwards.hpp"
+
+#include "boilerplate.hpp"
+#include "gibberish.hpp"
+#include "compute.hpp"
+#include "data_blocks.hpp"
+#include "psa_asset.hpp"
+#include "find_or_create_asset.hpp"
+#include "template_line.hpp"
+#include "tf_fuzz.hpp"
+#include "crypto_asset.hpp"
+#include "psa_call.hpp"
+#include "security_call.hpp"
+#include "secure_template_line.hpp"
+#include "sst_call.hpp"
+#include "sst_template_line.hpp"
+#include "sst_asset.hpp"
+#include "crypto_asset.hpp"
+
+
+
+/**********************************************************************************
+   Methods of class security_hash_template_line follow:
+**********************************************************************************/
+
+//**************** security_hash_template_line methods ****************
+
+bool security_hash_template_line::copy_template_to_asset (void)
+{
+    // The assets are not directly involved in this call.
+    return true;
+}
+
+bool security_hash_template_line::copy_template_to_call (void)
+{
+    // Find the call by serial number (must search;  may have moved).
+    for (auto call : test_state->calls) {
+        if (call->call_ser_no == call_ser_no) {
+            // Copy asset info to call object for creation code -- the entire vector:
+            for (auto as_name : asset_id.asset_name_vector) {
+                /* Also copy into template line object's local vector: */
+                call->asset_id.asset_name_vector.push_back (as_name);
+            }
+            call->asset_id.id_n = asset_id.id_n;
+                // this call is currently limited to name-based
+            call->asset_id.name_specified = true;
+            call->set_data.string_specified = false;  // shouldn't matter, but...
+            call->set_data.file_specified = false;
+            call->set_data.file_path.assign("");
+            call->asset_ser_no = asset_ser_no;  // TODO:  Does this make sense?
+            call->flags_string.assign ("");  call->set_data.set("");
+            call->how_asset_found = asset_search::found_active;
+            call->expect.pf_info_incomplete = true;
+            return true;
+        }
+    }
+    return false;  // somehow didn't find it the call.
+}
+
+security_hash_template_line::security_hash_template_line (tf_fuzz_info *resources)
+    : security_template_line (resources)
+{
+}
+// Default destructor:
+security_hash_template_line::~security_hash_template_line (void)
+{
+    return;  // just to have something to pin a breakpoint onto
+}
+
+// (Default constructor not used)
+
+
+/**********************************************************************************
+   End of methods of class security_hash_template_line.
+**********************************************************************************/
+
diff --git a/tools/tf_fuzz/template/secure_template_line.hpp b/tools/tf_fuzz/template/secure_template_line.hpp
new file mode 100644
index 0000000..302da1f
--- /dev/null
+++ b/tools/tf_fuzz/template/secure_template_line.hpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/* Objects typed to subclasses of the these classes are constructed and filled in
+   by the parser as it parses the template.  Although these objects do fairly
+   closely correspond to template lines, there's no real correlation to lines in
+   the generated code. */
+
+#ifndef SECURE_TEMPLATE_LINE_HPP
+#define SECURE_TEMPLATE_LINE_HPP
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <iterator>
+#include <algorithm>
+#include <new>
+
+/* 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.
+*/
+
+
+using namespace std;
+
+/* Note:  The following are sub-classed from security (above). */
+
+class security_hash_template_line : public security_template_line
+{
+public:
+    // Data members:
+    // Methods:
+        void setup_call (set_data_info set_data, bool random_data,
+                 bool fill_in_template, bool create_call, template_line *temLin,
+                 tf_fuzz_info *rsrc)
+        {
+            define_call<hash_call> (set_data, random_data,
+                            fill_in_template, create_call, temLin, rsrc);
+        }
+        bool copy_template_to_asset (void);
+        bool copy_template_to_call (void);
+        security_hash_template_line (tf_fuzz_info *resources);  // (constructor)
+        ~security_hash_template_line (void);
+
+protected:
+    // Data members:
+    // Methods:
+
+private:
+    // Data members:
+    // Methods:
+};
+
+#endif // #ifndef SECURE_TEMPLATE_LINE_HPP
+
diff --git a/tools/tf_fuzz/template/sst_template_line.cpp b/tools/tf_fuzz/template/sst_template_line.cpp
new file mode 100644
index 0000000..338764b
--- /dev/null
+++ b/tools/tf_fuzz/template/sst_template_line.cpp
@@ -0,0 +1,303 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "class_forwards.hpp"
+
+#include "boilerplate.hpp"
+#include "gibberish.hpp"
+#include "compute.hpp"
+#include "data_blocks.hpp"
+#include "psa_asset.hpp"
+#include "find_or_create_asset.hpp"
+#include "template_line.hpp"
+#include "tf_fuzz.hpp"
+#include "crypto_asset.hpp"
+#include "psa_call.hpp"
+#include "sst_call.hpp"
+#include "sst_template_line.hpp"
+#include "sst_asset.hpp"
+#include "crypto_asset.hpp"
+
+
+
+/**********************************************************************************
+   Methods of class set_sst_template_line follow:
+**********************************************************************************/
+
+//**************** set_sst_template_line methods ****************
+
+string set_sst_template_line::rand_creation_flags (void)
+{
+    return ((rand() % 2) == 1)?
+        "PSA_STORAGE_FLAG_WRITE_ONCE" : "PSA_STORAGE_FLAG_NONE";
+    /* TODO:  There's seems to be some uncertainty as to how many creation-flag
+       values are actually used, so for now only using PSA_STORAGE_FLAG_WRITE_ONCE
+       and PSA_STORAGE_FLAG_NONE.  If there are more in real-world use, then
+       resurrect the commented-out code below to assign them:
+    string result = "";
+    const int most_flags = 3,
+    int n_flags = (rand() % most_flags);
+
+    for (int i = 0;  i < ;  i < n_flags;  ++i) {
+        switch (rand() % 5) {
+            case 0:
+                result += "PSA_STORAGE_FLAG_WRITE_ONCE";
+                break;
+            case 1:
+                break;
+            case 2:
+                break;
+            case 3:
+                break;
+            case 4:
+                break;
+        }
+        if (i < n_flags-1)
+            result += " | ";
+    }
+    if (result == "") result = "PSA_STORAGE_FLAG_NONE";
+*/
+}
+
+set_sst_template_line::set_sst_template_line (tf_fuzz_info *resources)
+    : sst_template_line (resources)  // constructor)
+{
+    // Creation flags:
+    flags_string = rand_creation_flags();
+}
+
+
+
+bool set_sst_template_line::copy_template_to_asset (void)
+{
+    vector<psa_asset*>::iterator found_asset;
+    sst_asset* this_asset;
+    // Find the call by serial number (must search;  may have moved).
+    asset_search how_found = test_state->find_or_create_sst_asset (
+                        psa_asset_search::serial, psa_asset_usage::all, "", 0,
+                        asset_ser_no, yes_create_asset, found_asset );
+    // The vector is base-class, but this itself *really is* an sst_asset object:
+    if (how_found == asset_search::unsuccessful) {
+        cerr << "\nError:  Tool-internal:  TF-Fuzz failed to find a required asset."
+             << endl;
+        exit(108);
+    }
+    // Copy over everything relevant:
+    if (how_found != asset_search::not_found) {  // will be found for make calls, but not necessarily others
+        this_asset = reinterpret_cast<sst_asset*>(*found_asset);
+        this_asset->set_data.string_specified = set_data.string_specified;
+        this_asset->set_data.set (set_data.get());
+        this_asset->set_data.file_specified = set_data.file_specified;
+        this_asset->set_data.file_path.assign (set_data.file_path);
+        this_asset->flags_string = flags_string;
+        this_asset->set_uid (asset_id.id_n);
+        this_asset->asset_id.name_specified = asset_id.name_specified;
+        this_asset->asset_id.set_name (asset_id.get_name());
+    }
+    return true;
+}
+
+bool set_sst_template_line::copy_template_to_call (void)
+{
+    // Find the call by serial number (must search;  may have moved).
+    for (auto call : test_state->calls) {
+        if (call->call_ser_no == call_ser_no) {
+            // Copy asset info to call object for creation code:
+            call->asset_id.set_just_name (asset_id.get_name());
+                // TODO:  Question:  Just call->asset_id = asset_id?
+            call->asset_id.id_n = asset_id.id_n;
+            call->asset_id.name_specified = asset_id.name_specified;
+            call->set_data.string_specified =   set_data.string_specified
+                                             || set_data.random_data;
+            call->set_data.file_specified = set_data.file_specified;
+            call->set_data.file_path = set_data.file_path;
+            call->asset_ser_no = asset_ser_no;
+            call->flags_string = flags_string;  call->set_data.set (set_data.get());
+            call->how_asset_found = how_asset_found;
+            call->expect.pf_info_incomplete = true;
+            return true;
+        }
+    }
+    return false;  // somehow didn't find it the call.
+}
+
+// Default destructor:
+set_sst_template_line::~set_sst_template_line (void)
+{
+    return;  // just to have something to pin a breakpoint onto
+}
+
+// (Default constructor not used)
+
+
+
+/**********************************************************************************
+   End of methods of class set_sst_template_line.
+**********************************************************************************/
+
+
+/**********************************************************************************
+   Methods of class remove_sst_template_line follow:
+**********************************************************************************/
+
+remove_sst_template_line::remove_sst_template_line (tf_fuzz_info *resources)
+    : sst_template_line (resources)  // (constructor)
+{
+    is_remove = true;  // template_line's constructor defaults this to false
+}
+
+bool remove_sst_template_line::copy_template_to_asset (void)
+{
+    vector<psa_asset*>::iterator found_asset;
+    sst_asset* this_asset;
+    // Find the call by serial number (must search;  may have moved).
+    asset_search how_found = test_state->find_or_create_sst_asset (
+                        psa_asset_search::serial, psa_asset_usage::all, "", 0,
+                        asset_ser_no, dont_create_asset, found_asset );
+    // The vector is base-class, but this itself *really is* an sst_asset object:
+    if (how_found == asset_search::unsuccessful) {
+        cerr << "\nError:  Tool-internal:  TF-Fuzz failed to find a required asset."
+             << endl;
+        exit(108);
+    }
+    // Copy *the other way* on asset reads!
+    if (how_found != asset_search::not_found) {
+        this_asset = reinterpret_cast<sst_asset*>(*found_asset);
+           // Note: The vector is of base-class type, but the assets *are* sst_asset.
+        set_data.string_specified = this_asset->set_data.string_specified;
+        set_data.file_specified = this_asset->set_data.file_specified;
+        flags_string = this_asset->flags_string;
+        asset_id.id_n = this_asset->asset_id.id_n;
+        asset_id.name_specified = this_asset->asset_id.name_specified;
+    }
+    return true;
+}
+
+bool remove_sst_template_line::copy_template_to_call (void)
+{
+    // Find the call by serial number (must search;  may have moved).
+    for (auto call : test_state->calls) {
+        if (call->call_ser_no == call_ser_no) {
+            call->asset_id.set_just_name (asset_id.get_name());
+            call->asset_id.id_n = asset_id.id_n;
+            call->set_data.string_specified = false;
+            call->set_data.set ("");  call->id_string = asset_name;
+            call->set_data.file_specified = false;
+            call->set_data.file_path = "";  call->asset_ser_no = asset_ser_no;
+            call->how_asset_found = how_asset_found;
+            call->expect.pf_info_incomplete = true;
+            return true;
+        }
+    }
+    return false;  // somehow didn't find it the call.
+}
+
+// Default destructor:
+remove_sst_template_line::~remove_sst_template_line (void)
+{
+    return;  // just to have something to pin a breakpoint onto
+}
+
+// (Default constructor not used)
+
+
+/**********************************************************************************
+   End of methods of class remove_sst_template_line.
+**********************************************************************************/
+
+
+/**********************************************************************************
+   Methods of class read_sst_template_line follow:
+**********************************************************************************/
+
+read_sst_template_line::read_sst_template_line (tf_fuzz_info *resources)
+    : sst_template_line (resources)  // (constructor)
+{
+    char gibberish_buffer[4096];  string databuff;
+    int data_length;
+    set_data.string_specified = (rand()%2) == 1?  true : false;
+
+    // Go ahead and create a literal-data string even if not needed:
+    data_length = test_state->gibbergen.pick_sentence_len();
+    test_state->gibbergen.sentence (gibberish_buffer, gibberish_buffer + data_length);
+    databuff = gibberish_buffer;  set_data.set (databuff);
+
+    set_data.file_specified = (!set_data.string_specified && (rand()%2) == 1)?  true : false;
+    set_data.file_path = "";  // can't really devise a random path
+}
+
+bool read_sst_template_line::copy_template_to_asset (void)
+{
+    vector<psa_asset*>::iterator found_asset;
+    sst_asset* this_asset;
+    // Find the call by serial number (must search;  may have moved).
+    asset_search how_found = test_state->find_or_create_sst_asset (
+                        psa_asset_search::serial, psa_asset_usage::all, "", 0,
+                        asset_ser_no, dont_create_asset, found_asset );
+    // The vector is base-class, but this itself *really is* an sst_asset object:
+    if (how_found == asset_search::unsuccessful) {
+        cerr << "\nError:  Tool-internal:  TF-Fuzz failed to find a required asset."
+             << endl;
+        exit(108);
+    }
+    // Copy *the other way* on asset reads!
+    if (how_found != asset_search::not_found) {  // will be found for make calls, but not necessarily others
+        this_asset = reinterpret_cast<sst_asset*>(*found_asset);
+        set_data.string_specified = this_asset->set_data.string_specified;
+        set_data.file_specified = this_asset->set_data.file_specified;
+        flags_string = this_asset->flags_string;
+        asset_id.id_n = this_asset->asset_id.id_n;
+        asset_id.name_specified = this_asset->asset_id.name_specified;
+    }
+    return true;
+    // TODO:  Shouldn't data be copied over?
+}
+
+bool read_sst_template_line::copy_template_to_call (void)
+{
+    // Find the call by serial number (must search;  may have moved).
+    for (auto call : test_state->calls) {
+        if (call->call_ser_no == call_ser_no) {
+            call->asset_id.set_just_name (asset_id.get_name());
+            call->asset_id.id_n = asset_id.id_n;
+            call->set_data.string_specified
+                    = set_data.string_specified || set_data.random_data;
+            call->set_data.set(set_data.get());
+            call->assign_data_var = assign_data_var;
+            call->assign_data_var_specified = assign_data_var_specified;
+            // TODO:  Just copy entire expect object?  call->expect = expect;
+            call->expect.data_var = expect.data_var;
+            call->expect.data_var_specified = expect.data_var_specified;
+            call->expect.data_specified = expect.data_specified;
+            call->expect.data.assign(expect.data);
+            call->expect.pf_info_incomplete = true;
+            call->id_string = asset_name;  // data = expected
+            call->set_data.file_specified = set_data.file_specified;
+            call->set_data.file_path = set_data.file_path;  call->asset_ser_no = asset_ser_no;
+            call->flags_string = flags_string;
+            call->how_asset_found = how_asset_found;
+            call->print_data = print_data;
+            call->hash_data = hash_data;
+            return true;
+        }
+    }
+    return false;  // somehow didn't find it the call
+}
+
+// Default destructor:
+read_sst_template_line::~read_sst_template_line (void)
+{
+    return;  // just to have something to pin a breakpoint onto
+}
+
+// (Default constructor not used)
+
+
+/**********************************************************************************
+   End of methods of class read_sst_template_line.
+**********************************************************************************/
+
diff --git a/tools/tf_fuzz/template/sst_template_line.hpp b/tools/tf_fuzz/template/sst_template_line.hpp
new file mode 100644
index 0000000..15703ba
--- /dev/null
+++ b/tools/tf_fuzz/template/sst_template_line.hpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef SST_TEMPLATE_LINE_HPP
+#define SST_TEMPLATE_LINE_HPP
+
+#include <cstdlib>  // for rand()
+
+/* This project's header files #including other project headers quickly becomes
+   unrealistically complicated.  The only solution is for each .cpp to include
+   the headers it needs.
+#include "psa_asset.hpp"
+#include "template_line.hpp"
+#include "psa_call.hpp"
+*/
+
+
+using namespace std;
+
+class set_sst_template_line : public sst_template_line
+{
+public:
+    // Data members:
+    // Methods:
+        bool copy_template_to_asset (void);
+        bool copy_template_to_call (void);
+        void setup_call (set_data_info set_info, bool random_data,
+                    bool fill_in_template, bool create_call, template_line *temLin,
+                    tf_fuzz_info *rsrc) {
+            define_call<sst_set_call> (set_info, random_data,
+                            fill_in_template, create_call, temLin, rsrc);
+        }
+        set_sst_template_line (tf_fuzz_info *resources);  // (constructor)
+        ~set_sst_template_line (void);
+
+protected:
+    // Data members:
+    // Methods:
+        string rand_creation_flags (void);  // choose a random set of creation flags
+
+private:
+    // Data members:
+    // Methods:
+};
+
+class remove_sst_template_line : public sst_template_line
+{
+public:
+    // Data members:
+    // Methods:
+        bool copy_template_to_asset (void);
+        bool copy_template_to_call (void);
+        void setup_call (set_data_info set_info, bool random_data,
+                            bool fill_in_template, bool create_call,
+                            template_line *temLin, tf_fuzz_info *rsrc) {
+            define_call<sst_remove_call> (set_info, random_data,
+                            fill_in_template, create_call, temLin, rsrc);
+        }
+        remove_sst_template_line (tf_fuzz_info *resources);  // (constructor)
+        ~remove_sst_template_line (void);
+
+protected:
+    // Data members:
+    // Methods:
+
+private:
+    // Data members:
+    // Methods:
+};
+
+class read_sst_template_line : public sst_template_line
+{
+public:
+    // Data members:
+    // Methods:
+        bool copy_template_to_asset (void);
+        bool copy_template_to_call (void);
+        void setup_call (set_data_info set_info, bool random_data,
+                            bool fill_in_template, bool create_call,
+                            template_line *temLin, tf_fuzz_info *rsrc) {
+            define_call<sst_get_call> (set_info, random_data,
+                            fill_in_template, create_call, temLin, rsrc);
+        }
+        read_sst_template_line (tf_fuzz_info *resources);  // (constructor)
+        ~read_sst_template_line (void);
+
+protected:
+    // Data members:
+    // Methods:
+
+private:
+    // Data members:
+    // Methods:
+};
+
+#endif  // #ifndef SST_TEMPLATE_LINE_HPP
diff --git a/tools/tf_fuzz/template/template_line.cpp b/tools/tf_fuzz/template/template_line.cpp
new file mode 100644
index 0000000..6ba6274
--- /dev/null
+++ b/tools/tf_fuzz/template/template_line.cpp
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+ /* Objects of these types are new()ed as a test-template line is parsed, and are
+    resolved to be the type of template command stated -- "create a key," "remove
+    an SST asset," or similar.  Parameters of the template line are parsed into
+    the object's members, where specified, but those members are randomized upon
+    construction.  Thus, any parameters not "nailed down," get randomized.
+ */
+
+#include <vector>
+#include <algorithm>  // for STL find()
+
+#include "class_forwards.hpp"
+
+#include "data_blocks.hpp"
+#include "boilerplate.hpp"
+#include "randomization.hpp"
+#include "gibberish.hpp"
+#include "compute.hpp"
+#include "psa_asset.hpp"
+#include "find_or_create_asset.hpp"
+#include "template_line.hpp"
+#include "tf_fuzz.hpp"
+#include "crypto_asset.hpp"
+#include "psa_call.hpp"
+#include "crypto_call.hpp"
+#include "sst_asset.hpp"
+#include "crypto_asset.hpp"
+
+
+
+/**********************************************************************************
+   Methods of class template_line follow:
+**********************************************************************************/
+
+// Constructor, passing in the tf_fuzz object for reference to all objects:
+template_line::template_line (tf_fuzz_info *resources) : test_state(resources)
+{
+    set_data.file_path.assign ("");
+    assign_data_var_specified = false;
+    flags_string.assign ("");
+    random_asset = psa_asset_usage::all;
+        // if not deleting a random asset of a certain type, then search all as usual
+    set_data.file_specified = false;
+    print_data = hash_data = false;
+    is_remove = false;  // will correct this in the remove case
+}
+
+/**********************************************************************************
+   Class template_line methods regarding setting and getting asset-names follow:
+**********************************************************************************/
+
+// Default destructor:
+template_line::~template_line (void)
+{
+    // Destruct the vectors of asset names/IDs:
+    asset_id.asset_name_vector.erase (asset_id.asset_name_vector.begin(), asset_id.asset_name_vector.end());
+    asset_id.asset_id_n_vector.erase (asset_id.asset_id_n_vector.begin(), asset_id.asset_id_n_vector.end());
+}
+
+// (Default constructor not used)
+
+/**********************************************************************************
+   End of methods of class template_line.
+**********************************************************************************/
+
+
+/**********************************************************************************
+   Methods of class sst_template_line follow:
+**********************************************************************************/
+
+sst_template_line::sst_template_line (tf_fuzz_info *resources) : template_line (resources)
+{
+    asset_type = psa_asset_type::sst;
+    return;  // just to have something to pin a breakpoint onto
+}
+
+// Default destructor:
+sst_template_line::~sst_template_line (void)
+{
+    // No real clean-up needed.
+    return;  // just to have something to pin a breakpoint onto
+}
+
+// (Default constructor not used)
+
+
+
+/**********************************************************************************
+   End of methods of class sst_template_line.
+**********************************************************************************/
+
+
+/**********************************************************************************
+   Methods of class key_template_line follow:
+**********************************************************************************/
+
+key_template_line::key_template_line (tf_fuzz_info *resources) : template_line (resources)
+{
+    // Note:  Similar random initialization for asset and template
+    // Randomize handle:
+    // TODO:  Key handles appear to be a lot more complex a question than the below
+    asset_type = psa_asset_type::key;
+    string wrong_data;  // holder for random data to be overwritten
+    gibberish *gib = new gibberish;
+    handle_str = gib->word (false, const_cast<char*>(wrong_data.c_str()),
+                            const_cast<char*>(  wrong_data.c_str())
+                                              + set_data.get().length()-1);
+    // Randomize key type:
+    key_type = rand_key_type();
+    // Randomize lifetime:
+    lifetime_str = ((rand() % 2) == 1)?
+                       "PSA_KEY_LIFETIME_VOLATILE" : "PSA_KEY_LIFETIME_PERSISTENT";
+    // Choose a random expected key size in bits:
+    expected_n_bits = to_string(rand()%10000);
+}
+
+// Create ID-based name:
+string key_template_line::make_id_based_name (uint64_t id_n, string &name)
+{
+    string result = "Key_ID_";
+    result.append(to_string(id_n));
+    return result;
+}
+
+// Default destructor:
+key_template_line::~key_template_line (void)
+{
+    // No real clean-up needed.
+    return;  // just to have something to pin a breakpoint onto
+}
+
+// (Default constructor not used)
+
+
+
+/**********************************************************************************
+   End of methods of class key_template_line.
+**********************************************************************************/
+
+
+/**********************************************************************************
+   Methods of class policy_template_line follow:
+**********************************************************************************/
+
+policy_template_line::policy_template_line (tf_fuzz_info *resources)
+            : template_line (resources)
+{
+    asset_type = psa_asset_type::policy;
+    // Randomize key-policy usage and algorithm:
+    policy_usage = rand_key_usage();
+    policy_algorithm = rand_key_algorithm();
+}
+
+// Create ID-based name:
+string policy_template_line::make_id_based_name (uint64_t id_n, string &name)
+{
+    string result = "Policy_ID_";
+    result.append(to_string(id_n));
+    //
+    return result;
+}
+
+// Default destructor:
+policy_template_line::~policy_template_line (void)
+{
+    // No real clean-up needed.
+    return;  // just to have something to pin a breakpoint onto
+}
+
+// (Default constructor not used)
+
+
+
+/**********************************************************************************
+   End of methods of class policy_template_line.
+**********************************************************************************/
+
+
+/**********************************************************************************
+   Methods of class security_template_line follow:
+**********************************************************************************/
+
+security_template_line::security_template_line (tf_fuzz_info *resources)
+            : template_line (resources)
+{
+}
+
+// Default destructor:
+security_template_line::~security_template_line (void)
+{
+    // No real clean-up needed.
+    return;  // just to have something to pin a breakpoint onto
+}
+
+// (Default constructor not used)
+
+
+/**********************************************************************************
+   End of methods of class security_template_line.
+**********************************************************************************/
+
diff --git a/tools/tf_fuzz/template/template_line.hpp b/tools/tf_fuzz/template/template_line.hpp
new file mode 100644
index 0000000..ef843ac
--- /dev/null
+++ b/tools/tf_fuzz/template/template_line.hpp
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/* Objects typed to subclasses of the these classes are constructed and filled in
+   by the parser as it parses template lines.  There is not necessarily a one-to-one
+   correspondence between the template lines and either the PSA commands generated
+   nor PSA assets they manipulate.  PSA assets (which persist through the test) and
+   PSA commands are therefore tracked in separate objects, but referenced here. */
+
+#ifndef TEMPLATE_LINE_HPP
+#define TEMPLATE_LINE_HPP
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <iterator>
+#include <algorithm>
+#include <new>
+
+/* 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.
+*/
+
+
+using namespace std;
+
+class template_line
+{
+public:
+    // Data members:  // low value to hide these behind setters and getters
+        // Everything about the test -- accumulated PSA commands, assets, etc.:
+        tf_fuzz_info *test_state;
+        /* Note:  The following are pointers to the psa_asset and psa_call currently
+           being worked with.  These objects these are first placed on the appropriate
+           vector in test_state of such objects, and then referenced here. */
+        psa_asset_type asset_type;  // SST vs. key vs. policy (etc.)
+        expect_info expect;  // everything about expected results
+        set_data_info set_data;  // everything about setting PSA-asset data
+        asset_name_id_info asset_id;  // everything about the asset(s) for this line
+        long call_ser_no;  // unique identifer for psa_call tracker object
+        long asset_ser_no;  // same for psa_asset objects
+            /* Note:  Regarding the above serial numbers, we can't save away iterators
+                      nor pointers, because STL vectors could get relocated.  Must
+                      explicitly search immediately prior to using these objects! */
+        psa_asset_usage random_asset;
+            /* if asked to use some random asset from active or deleted, this says
+               which.  psa_asset_usage::all if not using this feature. */
+        asset_search how_asset_found;
+        bool assign_data_var_specified;
+        string assign_data_var;  // name of variable to dump (assign) data into
+        bool print_data;  // true to print asset data to test log
+        bool hash_data;  // true to hash data for later comparison
+        /* Vectors of asset names or IDs.  These are used to create several similar
+           PSA calls from a single template line. */
+        bool is_remove;  // true if this template line is to remove an asset
+    // Methods (mostly for calling from within yyparse()):
+        virtual bool copy_template_to_asset (void) = 0;
+        virtual bool copy_template_to_call (void) = 0;
+        virtual void setup_call (set_data_info set_data, bool random_data,
+                                 bool fill_in_template, bool create_call,
+                                 template_line *temLin, tf_fuzz_info *rsrc) = 0;
+        template_line (tf_fuzz_info *resources);  // (constructor)
+        virtual ~template_line (void);
+
+protected:  // a lot simpler to just let subclasses access these directly
+    // Data members:
+        // Parallel vectors of PSA-asset info, by asset identified:
+        /* Not all template lines involve expected data, but all that do use it,
+           use it the same, so include it here. */
+        string asset_name;  // parsed from template, assigned to psa_asset object
+        string flags_string;  // creation flags
+    // Methods:
+
+private:
+    // Data members:
+    // Methods:
+};
+
+
+/* Note:  The following are sub-classed from template_line (above), and then further
+          subclassed in sst_template_line.*pp, crypto_template_line.*pp, etc.  Concep-
+          tually, these subclasses might be more logically put in those sub-classing
+          files, but this gives a more-even balance of file size and complexity. */
+
+class sst_template_line : public template_line
+{
+public:
+    // Data members:
+        // SST-asset info:
+        // PSA-call info:
+    // Methods:
+        sst_template_line (tf_fuzz_info *resources);  // (constructor)
+        ~sst_template_line (void);
+
+protected:
+    // Data members:
+    // Methods:
+
+private:
+    // Data members:
+    // Methods:
+};
+
+
+class key_template_line : public template_line
+{
+public:
+    // Data members:
+        string handle_str;  // the text name of the key's "handle"
+        string key_type;  // DES, AES, RAW, vendor, none, etc.
+        string lifetime_str;  // similarly, the text representation of the key's lifetime
+        string expected_n_bits;
+           // for get_key_info call (possibly others) exected key size in bits
+    // Methods:
+        string make_id_based_name (uint64_t id_n, string &name);  // create ID-based asset name
+        key_template_line (tf_fuzz_info *resources);  // (constructor)
+        ~key_template_line (void);
+
+protected:
+    // Data members:
+    // Methods:
+
+private:
+    // Data members:
+    // Methods:
+};
+
+class policy_template_line : public template_line
+{
+public:
+    // Data members:
+        string policy_usage;
+        string policy_algorithm;
+    // Methods:
+        policy_template_line (tf_fuzz_info *resources);  // (constructor)
+        ~policy_template_line (void);
+
+protected:
+    // Data members:
+    // Methods:
+
+private:
+    // Data members:
+    // Methods:
+        string make_id_based_name (uint64_t id_n, string &name);  // create ID-based asset name
+};
+
+
+class security_template_line : public template_line
+{
+public:
+    // Data members:  // low value to hide these behind setters and getters
+        // Everything about the test -- accumulated PSA commands, assets, etc.:
+    // Methods (for calling from within yyparse()):
+        security_template_line (tf_fuzz_info *resources);  // (constructor)
+        ~security_template_line (void);
+
+protected:  // a lot simpler to just let subclasses access these directly
+    // Data members:
+    // Methods:
+
+private:
+    // Data members:
+    // Methods:
+};
+
+
+#endif  // TEMPLATE_LINE_HPP
diff --git a/tools/tf_fuzz/tests/README b/tools/tf_fuzz/tests/README
new file mode 100644
index 0000000..292acda
--- /dev/null
+++ b/tools/tf_fuzz/tests/README
@@ -0,0 +1,12 @@
+.../tf_fuzz/tests directory contents:
+
+example_template  sstReads  sstSets
+
+--------------------------------------------------------------------------------
+
+These are perhaps more examples of test-template files, more than organized
+tests as such.
+
+--------------
+
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
diff --git a/tools/tf_fuzz/tests/example_template b/tools/tf_fuzz/tests/example_template
new file mode 100644
index 0000000..4ecfd53
--- /dev/null
+++ b/tools/tf_fuzz/tests/example_template
@@ -0,0 +1,20 @@
+purpose to check basic functionality of TF-Fuzz;
+
+/*// Attempt to get data from a deleted SST asset, using human-readable name:
+set sst name creditCardNos data "0985-9375-0338-3406";
+set sst name creditCardNos data "5687-3782-1127-9821";
+remove sst name creditCardNos;
+remove sst name creditCardNos;
+*/
+
+//remove sst name creditCardNos;
+
+//remove sst name creditCardNos expect user_defined_error;
+
+//read sst name creditCardNos dfname 'ccNumbersRead' expect uid_not_found;
+
+//set SST asset by raw UID number and then get its data:
+
+//set sst uid 38 data "Very short data set" expect nothing;
+
+//read sst uid 38 check "Very short data set" expect pass;
diff --git a/tools/tf_fuzz/tests/sstReads b/tools/tf_fuzz/tests/sstReads
new file mode 100644
index 0000000..d2ad8b9
--- /dev/null
+++ b/tools/tf_fuzz/tests/sstReads
@@ -0,0 +1,87 @@
+purpose to beat the heck out of read sst template lines;
+
+read sst name nonexistent check "XYZ PDQ";  // fail
+
+/*
+set sst name passwords data "Very short data set";
+read sst name passwords check "Very short data set";
+read sst name passwords check greeble;
+//read sst name passwords assign dorf;
+//read sst name passwords print;
+*/
+
+/*
+set sst uid 1234 data *;
+read sst uid 1234 check "Very short data set";
+//read sst uid 1234 check greeble;
+//read sst uid 1234 assign dorf;
+*/
+
+/*
+set sst name moe curly larry data *;
+remove sst *active;
+read sst *active assign shemp;
+read sst *active print;
+*/
+
+//read sst uid 205 assign aVariable;
+
+//read sst uid 15 41 check "self-destruct using top secret corbomite device" expect pass;
+
+//read sst uid 17 41 19 31 10 53 data *;
+
+/*
+set sst name apollo_11 data *;
+read sst name apollo_11 hash;
+*/
+
+/*
+set sst name jim lovell gemini_7 gemini_12 apollo_8 apollo_13 data *;
+read sst name jim lovell gemini_7 gemini_12 apollo_8 apollo_13 hash;
+secure hash neq jim lovell gemini_7 gemini_12 apollo_8 apollo_13;
+*/
+
+/*
+set sst name friendship_7 apollo_14 data *;
+read sst name friendship_7 apollo_14 hash;
+secure hash neq friendship_7 apollo_14;
+*/
+
+// /*
+set sst name astp data *;
+read sst name astp hash;
+secure hash neq astp;
+// */
+
+/*
+set sst name chapman cleese gilliam idle jones palin data *;
+4 of {
+    set sst name cleveland data *;
+    read sst *active check "totally wrong data";
+    remove sst *active;
+} */
+
+/*
+2 to 6 of {
+    read sst name passwords check "Very short data set";
+    read sst name CCnumbers check "Ask not what your country can do for you.";
+    read sst name * data *;
+    read sst uid * data * expect pass;
+} */
+
+/*
+shuffle {
+    read sst name passwords check "Very short data set";
+    read sst name CCnumbers data *;
+    read sst name Kirk check "Beam me up.";
+    read sst uid 42 check "Don't panic.";
+    read sst name Spock check "Fascinating." expect pass;
+    read sst name McCoy check "I'm a doctor, not a bricklayer." expect pass;
+    read sst name Scotty check "I'm giving her all she's got!" expect pass;
+} */
+
+/*
+read sst name neil buzz mike data *;
+remove sst *active expect pass;  // zap a random currently-active SST asset
+remove sst *deleted;  // delete an already-deleted asset
+*/
diff --git a/tools/tf_fuzz/tests/sstSets b/tools/tf_fuzz/tests/sstSets
new file mode 100644
index 0000000..fb0981d
--- /dev/null
+++ b/tools/tf_fuzz/tests/sstSets
@@ -0,0 +1,59 @@
+purpose to beat the heck out of set sst template lines;
+
+//set sst name passwords data "Very short data set";
+
+//set sst uid 15 41 data "self-destruct using top secret corbomite device" expect pass;
+
+//set sst uid 38 data "So long, and thanks for all the fish!" expect nothing;
+
+//set sst uid * data * expect pass;
+
+set sst name CCnumbers data *;
+
+//set sst name CCnumbers securityAnswers passwords data *;
+
+//set sst uid 17 41 19 31 10 53 data *;
+
+//3 of {set sst name * data "The trick to flying is to throw yourself at the ground, and miss.";}
+
+//5 of {set sst name snortwaggle data *;}
+
+//4 of set sst uid * data "that's one small step for [a] man;  one giant leap for mankind";
+
+//5 of set sst uid * data *;  // should have different data each time!
+
+/*
+4 of {
+    set sst name passwords data "Very short data set";
+    set sst name CCnumbers data "Beam me up, Scotty!";
+    set sst uid 1941 data "December 7th 1941:  A day that will live in infamy";
+    set sst name snortwaggle data * expect pass;
+    set sst name gurgleflurtz data "If you're going through hell, keep going.";
+    set sst name Picard data *;
+} */
+
+/*
+2 to 6 of {
+    set sst name passwords data "Very short data set";
+    set sst name CCnumbers data "Ask rather what you can do for your country.";
+    set sst name * data *;
+    set sst uid * data * expect pass;
+} */
+
+/*
+shuffle {
+    set sst name passwords data "Very short data set";
+    set sst name CCnumbers data *;
+    set sst name Kirk data "Beam me up.";
+    set sst uid 42 data "Don't panic.";
+    set sst name Spock data "Fascinating." expect pass;
+    set sst name McCoy data "I'm a doctor, not a bricklayer." expect pass;
+    set sst name Scotty data "I'm giving her all she's got!" expect pass;
+} */
+
+/*
+set sst name neil buzz mike data *;
+remove sst *active expect pass;  // zap a random currently-active SST asset
+remove sst *deleted;  // delete an already-deleted asset
+*/
+//set sst *deleted data "a over-ripe banana walks into a bar..." expect pass;
diff --git a/tools/tf_fuzz/tf_fuzz.cpp b/tools/tf_fuzz/tf_fuzz.cpp
new file mode 100644
index 0000000..4a153f6
--- /dev/null
+++ b/tools/tf_fuzz/tf_fuzz.cpp
@@ -0,0 +1,356 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <ctime>  // to seed random, if seed not passed in
+#include <string>
+#include <vector>
+#include <iostream>
+#include <cstdlib>  // for srand() and rand()
+#include <cstdio>  // for template lex&yacc input file
+#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 "find_or_create_asset.hpp"
+#include "template_line.hpp"
+#include "tf_fuzz.hpp"
+#include "sst_asset.hpp"
+#include "crypto_asset.hpp"
+#include "psa_call.hpp"
+#include "tf_fuzz_grammar.tab.hpp"
+
+
+extern FILE* yyin;  // telling lex&yacc which file to parse
+
+using namespace std;
+
+long psa_asset::unique_id_counter = 10;  // counts unique IDs for assets
+long psa_call::unique_id_counter = 10;  // counts unique IDs for assets
+    /* FYI:  Must initialize these class variables outside the class.  If
+             initialized inside the class, g++ requires they be const. */
+
+/**********************************************************************************
+   Methods of class tf_fuzz_info follow:
+**********************************************************************************/
+
+asset_search tf_fuzz_info::find_or_create_sst_asset (
+    psa_asset_search criterion,  // what to search on
+    psa_asset_usage where,  // where to search
+    string target_name,  // ignored if not searching on name
+    uint64_t target_id,  // also ignored if not searching on ID (e.g., SST UID)
+    long &serial_no,  // search by asset's unique serial number
+    bool create_asset,  // true to create the asset if it doesn't exist
+    vector<psa_asset*>::iterator &asset  // returns a pointer to requested asset
+) {
+    return generic_find_or_create_asset<sst_asset>(
+               active_sst_asset, deleted_sst_asset,
+               invalid_sst_asset, criterion, where, target_name, target_id,
+               serial_no, create_asset, asset
+           );
+}
+
+asset_search tf_fuzz_info::find_or_create_key_asset (
+    psa_asset_search criterion,  // what to search on
+    psa_asset_usage where,  // where to search
+    string target_name,  // ignored if not searching on name
+    uint64_t target_id,  // also ignored if not searching on ID (e.g., SST UID)
+    long &serial_no,  // search by asset's unique serial number
+    bool create_asset,  // true to create the asset if it doesn't exist
+    vector<psa_asset*>:: iterator &asset  // returns iterator to requested asset
+) {
+    return generic_find_or_create_asset<key_asset>(
+               active_key_asset, deleted_key_asset,
+               invalid_key_asset, criterion, where, target_name, target_id,
+               serial_no, create_asset, asset
+           );
+}
+
+asset_search tf_fuzz_info::find_or_create_policy_asset (
+    psa_asset_search criterion,  // what to search on
+    psa_asset_usage where,  // where to search
+    string target_name,  // ignored unless searching on name
+    uint64_t target_id,  // also ignored unless searching on ID (e.g., SST UID)
+    long &serial_no,  // search by asset's unique serial number
+    bool create_asset,  // true to create the asset if it doesn't exist
+    vector<psa_asset*>::iterator &asset  // returns iterator to requested asset
+) {
+    return generic_find_or_create_asset<policy_asset>(
+               active_policy_asset, deleted_policy_asset,
+               invalid_policy_asset, criterion, where, target_name, target_id,
+               serial_no, create_asset, asset
+           );
+}
+
+asset_search tf_fuzz_info::find_or_create_psa_asset (
+    psa_asset_type asset_type,  // what type of asset to find
+    psa_asset_search criterion,  // what to search on
+    psa_asset_usage where,  // where to search
+    string target_name,  // ignored if not searching on name
+    uint64_t target_id,  // also ignored if not searching on ID (e.g., SST UID)
+    long &serial_no,  // search by asset's unique serial number
+    bool create_asset,  // true to create the asset if it doesn't exist
+    vector<psa_asset*>::iterator &asset  // returns iterator to asset
+) {
+    switch (asset_type) {
+        case psa_asset_type::sst:
+            return find_or_create_sst_asset (
+                criterion, where, target_name, target_id,
+                serial_no, create_asset, asset);
+            break;
+        case psa_asset_type::key:
+            return find_or_create_key_asset (
+                criterion, where, target_name, target_id,
+                serial_no, create_asset, asset);
+            break;
+        case psa_asset_type::policy:
+            return find_or_create_policy_asset (
+                criterion, where, target_name, target_id,
+                serial_no, create_asset, asset);
+            break;
+        default:
+            cerr << "\nError:  Internal:  Please report error "
+                 << "#1503 to TF-Fuzz developers." << endl;
+            exit (1500);
+    }
+}
+
+// Remove any PSA resources used in the test.  Returns success==true, fail==false.
+void tf_fuzz_info::teardown_test (void)
+{
+    string call;
+    // Traverse through the SST-assets list, writing out remove commands:
+    for (auto &asset : active_sst_asset) {
+        call = bplate->bplate_string[teardown_sst];
+        find_replace_1st ("$uid", to_string(asset->asset_id.id_n), call);
+        call.append (bplate->bplate_string[teardown_sst_check]);
+        output_C_file << call;
+    }
+    // Same, but with key assets:
+    for (auto &asset : active_key_asset) {
+        call = bplate->bplate_string[teardown_key];
+        find_replace_1st ("$handle", asset->handle_str, call);
+        call.append (bplate->bplate_string[teardown_key_check]);
+        output_C_file << call;
+    }
+}
+
+// Write out the test itself.
+void tf_fuzz_info::write_test (void)
+{
+    string call;
+    string work = bplate->bplate_string[preamble_A];  // a temporary workspace string
+
+    // The test file should be open before calling this method.
+    // Spit out the obligatory preamble:
+    find_replace_all ("$purpose", test_purpose, work);
+    output_C_file << work;
+
+    // If using hashing, then spit out the hashing functions:
+    if (include_hashing_code) {
+        work = bplate->bplate_string[hashing_code];
+        output_C_file << work;
+    }
+
+    // Print out the second half of the preamble code:
+    work = bplate->bplate_string[preamble_B];
+    find_replace_all ("$purpose", test_purpose, work);
+    output_C_file << work;
+
+    output_C_file << "\n\n    /* Variables (etc.) to initialize and check PSA "
+                  << "assets: */" << endl;
+    for (auto call : calls) {
+        // Reminder:  calls is a vector of *pointers to* psa_call subclass objects.
+        call->fill_in_prep_code();
+        call->write_out_prep_code (output_C_file);
+    }
+
+    output_C_file << "\n\n    /* PSA calls to test: */" << endl;
+    for (auto call : calls) {
+        call->fill_in_command();  // (fills in check code too)
+        output_C_file << endl;
+        call->write_out_command (output_C_file);
+        call->write_out_check_code (output_C_file);
+    }
+
+    output_C_file << "\n\n    /* Removing assets left over from testing: */"
+                  << endl;
+    teardown_test();
+
+    // Seal the deal:
+    output_C_file << bplate->bplate_string[closeout];
+
+    // Close the template and test files:
+    output_C_file.close();
+    fclose (template_file);
+}
+
+
+/* Parse command-line parameters.  exit() if error(s) found.  Place results
+   into resource object. */
+void tf_fuzz_info::parse_cmd_line_params (int argc, char* argv[])
+{
+    int exit_val = 0;  // the linux return value, default 0, meaning all-good
+    vector<string> cmd_line_parameter, cmd_line_switch;
+        // (STL) vectors of hard cmd_line_parameter and cmd_line_switches
+    int n_parameters = 0, n_switches = 0;
+        // counting off cmd_line_parameter and cmd_line_switches while parsing
+    char testc;
+
+    // Parse arguments into lists of strings:
+    for (int i = 1;  i < argc;  ++i) {
+        if (argv[i][0] == '-') {  // cmd_line_switch
+            if (argv[i][1] == '-') {  // double-dash
+                cmd_line_switch.push_back (string(argv[i]+2));
+            } else {  // single-dash cmd_line_switch;  fine either way
+                cmd_line_switch.push_back (string(argv[i]+1));
+            }
+            ++n_switches;
+        } else {  // hard cmd_line_parameter
+            cmd_line_parameter.push_back(argv[i]);
+            ++n_parameters;
+        }
+    }
+    // If too-few or too many cmd_line_parameter supplied
+    for (int i = 0;  i < n_switches;  ++i) {
+        // If usage string requested...
+        if (cmd_line_switch[i] == "h") {
+            exit_val = 10;
+        }
+        // If verbose requested, make note:
+        if (cmd_line_switch[i] == "v") {
+            verbose_mode = true;
+        }
+    }
+    if (exit_val == 10) {  // -h switch
+        cout << "\nHow to run TF-Fuzz:" << endl;
+    } else if (n_parameters < 2) {
+        cerr << "\nToo few command-line parameters." << endl;
+        exit_val = 11;
+    } else if (n_parameters > 3) {
+        cerr << "\nToo many command-line parameters." << endl;
+        exit_val = 12;
+    } else {
+        template_file_name = cmd_line_parameter[0];
+        template_file = fopen (template_file_name.c_str(), "r");
+        test_output_file_name = cmd_line_parameter[1];
+        output_C_file.open (test_output_file_name, ios::out);
+        if (n_parameters == 3) {
+            /* TODO:  The try-catch below doesn't always seem to work.  For now,
+               manually "catch" the most basic problem: */
+            testc = cmd_line_parameter[2][0];
+            if (testc < '0' || testc > '9') {
+                cerr << "\nError:  Random-seed value (third parameter) could "
+                     << "not be interpreted as a number." << endl;
+                rand_seed = 0;
+            } else {
+                try {
+                    rand_seed = stol (cmd_line_parameter[2], 0, 0);
+                } catch (int excep) {
+                    excep = 0;  // (keep compiler from complaining about not using excep)
+                    cerr << "\nWarning:  Random-seed value (third parameter) could "
+                         << "not be interpreted as a number." << endl;
+                    rand_seed = 0;
+                }
+            }
+        }
+        if (rand_seed == 0 || n_parameters < 3) {
+            if (n_parameters < 3) {
+                cout << "Info:  random seed was not specified." << endl;
+            } else {
+                cout << "Warning:  random seed, " << cmd_line_parameter[2]
+                     << ", was not usable!" << endl;
+            }
+            srand((unsigned int) time(0));  // TODO:  ideally, XOR or add in PID#
+            rand_seed = rand();
+                /* doesn't really matter, but it just "feels better" when the
+                   default seed value is itself more random. */
+        }
+        cout << endl << "Using seed value of " << dec << rand_seed << " " << hex
+             << "(0x" << rand_seed << ")." << endl;
+        srand(rand_seed);
+        if (template_file == NULL) {
+            cerr << "\nError:  Template file " << template_file_name
+                 << " could not be opened." << endl;
+            exit_val = 13;
+        } else if (!output_C_file.is_open()) {
+            // If test-output file couldn't be opened
+            cerr << "\nError:  Output C test file " << test_output_file_name
+                 << " could not be opened." << endl;
+            exit_val = 14;
+        }
+        // Default (not entirely worthless) purpose of the test:
+        test_purpose.assign (  "template = " + template_file_name + ", seed = "
+                             + to_string(rand_seed));
+    }
+    // Bad command line, or request for usage blurb, so tell them how to run us:
+    if (exit_val != 0) {
+        cout << endl << argv[0] << " usage:" << endl;
+        cout << "    Basic cmd_line_parameter (positional, in order, "
+             << "left-to-right):" << endl;
+        cout << "        Test-template file" << endl;
+        cout << "        Test-output .c file" << endl;
+        cout << "        (optional) random seed value" << endl;
+        cout << "    Optional switches:" << endl;
+        cout << "        -h or --h:  This help (command-line usage) summary."
+             << endl;
+        cout << "        -v or --v:  Verbose mode." << endl;
+        cout << "Examples:" << endl;
+        cout << "    " << argv[0] << " -h" << endl;
+        cout << "    " << argv[0] << " template.txt output_test.c 0x5EED" << endl;
+        exit (exit_val);
+    }
+}
+
+tf_fuzz_info::tf_fuzz_info (void)  // (constructor)
+{
+    this->bplate = new boilerplate();
+    test_purpose = template_file_name = test_output_file_name = "";
+    rand_seed = 0;
+    verbose_mode = false;
+    include_hashing_code = false;  // default
+}
+
+tf_fuzz_info::~tf_fuzz_info (void)
+{
+    delete bplate;
+}
+
+/**********************************************************************************
+   End of methods of class tf_fuzz_info.
+**********************************************************************************/
+
+
+int main(int argc, char* argv[])
+{
+    cout << "Trusted Firmware Fuzzer (TF-Fuzz) starting..." << endl << endl;
+
+    // Allocate "the world":
+    tf_fuzz_info *rsrc = new tf_fuzz_info;
+
+    // Parse parameters and open files:
+    rsrc->parse_cmd_line_params (argc, argv);
+
+    // Parse the test-template file:
+    yyin = rsrc->template_file;
+    int parse_result = yyparse (rsrc);
+
+    if (parse_result == 1) {
+        cerr << "\nError:  Template file has errors." << endl;
+    } else if (parse_result == 2) {
+        cerr << "\nError:  Sorry, TF-Fuzz ran out of memory." << endl;
+    }
+
+    cout << "Writing test file, " << rsrc->test_output_file_name << "." << endl;
+    rsrc->write_test();
+    rsrc->output_C_file.close();
+
+    cout << endl << "TF-Fuzz test generation complete." << endl;
+    return 0;
+}
diff --git a/tools/tf_fuzz/tf_fuzz.hpp b/tools/tf_fuzz/tf_fuzz.hpp
new file mode 100644
index 0000000..7668998
--- /dev/null
+++ b/tools/tf_fuzz/tf_fuzz.hpp
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef TF_FUZZ_HPP
+#define TF_FUZZ_HPP
+
+#include <string>
+#include <vector>
+#include <iostream>
+#include <fstream>
+
+
+/* This project's header files #including other project headers quickly becomes
+   unrealistically complicated.  The only solution is for each .cpp to include
+   the headers it needs.
+#include "psa_call.hpp"
+#include "sst_asset.hpp"
+#include "crypto_asset.hpp"
+#include "boilerplate.hpp"
+*/
+
+using namespace std;
+
+/* class tf_fuzz_info mostly just groups together everything needed to gather, then
+   write out the test.  This, so that they can be passed into the parser. */
+
+class tf_fuzz_info
+{
+    /* In creating a test, TF-Fuzz collects together a vector of strings cataloging
+       data structures used by PSA commands, and a vector of PSA call objects.  Once
+       the template is completely parsed, write_test() writes it all out.  The
+       process of creating these structures also requires the boilerplate text
+       strings.  In the process of building the test, it must track PSA assets to
+       "model" expected results of calls. */
+
+public:
+    // Data members (this class is mostly just to group stuff together, so public):
+        vector<string> prep_code;  // variable declarations to write out to test file
+        vector<psa_call*> calls;
+            /* the calls to perform:  Note:  must be vector *psa_call;  a vector of
+               psa_call does not allow (run-time) polymorphism. */
+        boilerplate *bplate;  // the boilerplate text for building the test
+        gibberish gibbergen;  // the gibberish asset-data generator
+        crc32 hashgen;  // simple 32-bit LFSR-based hashing generator
+        /* Note:  The following asset-lists are kept in base-class type to allow a
+                  common template-line processing function in tf_fuzz_grammar.y. */
+        vector<psa_asset*> active_sst_asset;  // list of known and usable SST assets
+        vector<psa_asset*> deleted_sst_asset;  // deleted SST assets
+        vector<psa_asset*> invalid_sst_asset;  // SST assets with invalid attributes
+        vector<psa_asset*> active_key_asset;  // list of known and usable keys
+        vector<psa_asset*> deleted_key_asset;  // deleted keys
+        vector<psa_asset*> invalid_key_asset;  // keys with invalid attributes
+        vector<psa_asset*> active_policy_asset;  // list of known, usable policies
+        vector<psa_asset*> deleted_policy_asset;  // deleted policies
+        vector<psa_asset*> invalid_policy_asset;  // policies with invalid attrs
+        string test_purpose;  // one text substitution to be performed at the top level
+        long rand_seed;  // the original random seed, whether passed in or defaulted
+        string template_file_name, test_output_file_name;
+        FILE *template_file;
+            /* handle to the test-template input file.  Unfortunately I can't seem to
+               get lex/yacc to understand C++ file references, probably because I'm
+               "extern C"ing the Lex content (Yacc/Bison turns out to be a lot easier
+               to coerce into generating C++ code than (F)Lex). */
+        ofstream output_C_file;  // handle to the output C test file
+        bool verbose_mode;  // true to "think aloud"
+        bool include_hashing_code;  // true to instantiate the hashing code
+    // Methods:
+        asset_search find_or_create_sst_asset (
+            psa_asset_search criterion,  // what to search on
+            psa_asset_usage where,  // where to search
+            string target_name,  // ignored if not searching on name
+            uint64_t target_id,  // ignored if not searching on ID (e.g., SST UID)
+            long &serial_no,  // search by asset's unique serial number
+            bool create_asset,  // true to create the asset if it doesn't exist
+            vector<psa_asset*>::iterator &asset  // returns a pointer to asset
+        );
+        asset_search find_or_create_key_asset (
+            psa_asset_search criterion,  // what to search on
+            psa_asset_usage where,  // where to search
+            string target_name,  // ignored if not searching on name
+            uint64_t target_id,  // also ignored if not searching on ID (e.g., SST UID)
+            long &serial_no,  // search by asset's unique serial number
+            bool create_asset,  // true to create the asset if it doesn't exist
+            vector<psa_asset*>:: iterator &asset  // returns iterator to asset
+        );
+        asset_search find_or_create_policy_asset (
+            psa_asset_search criterion,  // what to search on
+            psa_asset_usage where,  // where to search
+            string target_name,  // ignored if not searching on name
+            uint64_t target_id,  // also ignored if not searching on ID (e.g., SST UID)
+            long &serial_no,  // search by asset's unique serial number
+            bool create_asset,  // true to create the asset if it doesn't exist
+            vector<psa_asset*>::iterator &asset  // returns iterator to asset
+        );
+        asset_search find_or_create_psa_asset (
+            psa_asset_type asset_type,  // what type of asset to find
+            psa_asset_search criterion,  // what to search on
+            psa_asset_usage where,  // where to search
+            string target_name,  // ignored if not searching on name
+            uint64_t target_id,  // also ignored if not searching on ID (e.g., SST UID)
+            long &serial_no,  // search by asset's unique serial number
+            bool create_asset,  // true to create the asset if it doesn't exist
+            vector<psa_asset*>::iterator &asset  // returns iterator to asset
+        );
+        void teardown_test(void);  // removes any PSA resources used in the test
+        void write_test (void);  // returns success==true, fail==false
+        void parse_cmd_line_params (int argc, char* argv[]);
+            // parse command-line parameters, and open files
+        tf_fuzz_info (void);  // (constructor)
+        ~tf_fuzz_info (void);
+
+protected:
+    // Data members:
+        vector<string> teardown_calls;
+            // list of PSA commands to remove assets left over upon test completion
+    // Methods:
+
+private:
+    // Data members:
+    // Methods:
+};
+
+
+/*--------------------------------------------------------------
+   Helper functions:
+--------------------------------------------------------------*/
+
+
+template<typename CALL_TYPE>
+void define_call (set_data_info set_data, bool random_data, bool fill_in_template,
+                 bool create_call, template_line *temLin, tf_fuzz_info *rsrc
+) {
+    CALL_TYPE *the_call;
+    gibberish gib;
+    char gib_buff[1000];
+    string t_string;
+
+    if (fill_in_template) {
+        if (set_data.literal_data_not_file) {
+            if (random_data) {
+                int rand_data_length = 10 + (rand() % 800);
+                gib.sentence (gib_buff, gib_buff + rand_data_length - 1);
+                t_string = gib_buff;
+                temLin->set_data.set_calculated (t_string);
+            }
+        } else {
+            if (set_data.file_path == "") {  // catch the most likely failure at least!
+                cerr << "Error:  Tool-internal:  Please report error "
+                     << "#407 to the TF-Fuzz developers." << endl;
+                exit(407);
+            }
+            temLin->set_data.set_file (set_data.file_path);
+                // set in sst_asset_make_file_path
+        }
+    }
+    if (create_call) {
+        if (temLin->how_asset_found == asset_search::unsuccessful) {
+            cerr << "Error:  Tool-internal:  Please report error "
+                 << "#401 to the TF-Fuzz developers." << endl;
+            exit(401);
+        }
+        the_call = new CALL_TYPE (rsrc, temLin->call_ser_no,
+                                  temLin->how_asset_found);
+        rsrc->calls.push_back(the_call);  /* (note: this is not a memory leak!) */
+        temLin->copy_template_to_asset();
+        if (!temLin->copy_template_to_call()) {
+            cerr << "Error:  Tool-internal:  Please report error "
+                 << "#402 to the TF-Fuzz developers." << endl;
+            exit(402);
+        }
+    }
+}
+
+#endif  // #ifndef TF_FUZZ_HPP
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
diff --git a/tools/tf_fuzz/visualStudio/README b/tools/tf_fuzz/visualStudio/README
new file mode 100644
index 0000000..58c40f5b
--- /dev/null
+++ b/tools/tf_fuzz/visualStudio/README
@@ -0,0 +1,16 @@
+.../tf_fuzz/visualStudio directory contents:
+
+unistd.c  unistd.h
+
+--------------------------------------------------------------------------------
+
+This is just things to support running and debug under Microsoft Visual Studio.
+So far, it contains a "stand-in" for the unistd.h library, and more specifically,
+the isatty() call in that library, which is used by Lex&YACC.  Other functions
+may be added later as needed.  At some time in the future, an up-coming "inter-
+active mode" for interactively creating test templates may need an actual working
+isatty(), but that's not ready yet.
+
+--------------
+
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
diff --git a/tools/tf_fuzz/visualStudio/unistd.c b/tools/tf_fuzz/visualStudio/unistd.c
new file mode 100644
index 0000000..4b6c527
--- /dev/null
+++ b/tools/tf_fuzz/visualStudio/unistd.c
@@ -0,0 +1,3 @@
+int isatty(int arg) {

+	return 0;

+}
\ No newline at end of file
diff --git a/tools/tf_fuzz/visualStudio/unistd.h b/tools/tf_fuzz/visualStudio/unistd.h
new file mode 100644
index 0000000..e81dbbb
--- /dev/null
+++ b/tools/tf_fuzz/visualStudio/unistd.h
@@ -0,0 +1,2 @@
+#pragma once

+int isatty(int);
\ No newline at end of file