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