Add tf_fuzz tool
This is fully derived from tf-m repo.
Signed-off-by: Karl Zhang <karl.zhang@arm.com>
Change-Id: I8d35e70eda9081af66d8fa3f3cb4beb1d953060e
diff --git a/tf_fuzz/Makefile b/tf_fuzz/Makefile
new file mode 100644
index 0000000..0e98dc6
--- /dev/null
+++ b/tf_fuzz/Makefile
@@ -0,0 +1,231 @@
+# 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/variables.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/variables.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/variables.cpp utility/gibberish.cpp utility/randomization.cpp \
+ utility/string_ops.cpp utility/compute.cpp boilerplate/boilerplate.cpp \
+ tf_fuzz.cpp &
+ $(EDITOR) tests/example_template Makefile tests/sstSets tests/sstReads \
+ lib/tfm_boilerplate.txt boilerplate/boilerplate.hpp &
+
+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/variables.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/variables.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_blocks.o: utility/data_blocks.hpp utility/data_blocks.cpp Makefile
+ g++ -Wall -std=c++11 -O0 -g -c $(includes) -o utility/data_blocks.o \
+ utility/data_blocks.cpp
+
+utility/variables.o: utility/find_or_create_asset.hpp \
+utility/variables.hpp utility/variables.cpp Makefile
+ g++ -Wall -std=c++11 -O0 -g -c $(includes) -o utility/variables.o \
+ utility/variables.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 utility/variables.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 utility/variables.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 utility/variables.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 utility/variables.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 utility/variables.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_blocks.o \
+utility/variables.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_blocks.o \
+ utility/variables.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 demo/tossThis*
diff --git a/tf_fuzz/README b/tf_fuzz/README
new file mode 100644
index 0000000..32754c2
--- /dev/null
+++ b/tf_fuzz/README
@@ -0,0 +1,154 @@
+.../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 generate a testsuite for TF-M from a set of template files, use
+generate_test_suite.sh.
+
+.. code-block:: bash
+
+ Usage: generate_test_suite.sh <template_dir> <suites_dir>
+
+ Where:
+ template_dir: The directory containing template files for the
+ fuzzing tool
+ suites_dir: The suites directory in the TF-M working copy.
+ i.e.: $TF-M_ROOT/test/suites
+ Example:
+ cd tools/tf_fuzz
+ ./generate_test_suite.sh $TF-M_ROOT/tools/tf_fuzz/tests/ $TF-M_ROOT/../tf-m-tests/test/suites/
+
+
+After the test suite is generated, the new test suite needs to be added to the
+TF-M build by providing the following options to the CMake generate command
+(The path needs to be aligned with the test suite dir provided for the shell
+script above):
+
+.. code-block:: bash
+
+ -DTFM_FUZZER_TOOL_TESTS=1
+ -DTFM_FUZZER_TOOL_TESTS_CMAKE_INC_PATH=$TF-M_ROOT/test/suites/tf_fuzz
+
+--------------------------------------------------------------------------------
+
+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/tf_fuzz/assets/README b/tf_fuzz/assets/README
new file mode 100644
index 0000000..870416e
--- /dev/null
+++ b/tf_fuzz/assets/README
@@ -0,0 +1,10 @@
+This directory contains C++ header and program files for classes of objects that
+track PSA assets, notably during the Simulate phase.
+
+For more information, please browse to:
+
+ https://ci.trustedfirmware.org/job/tf-m-build-test-nightly/lastSuccessfulBuild/artifact/build-docs/tf-m_documents/install/doc/user_guide/html/docs/user_guides/tf_fuzz/asset_dir.html
+
+--------------
+
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
diff --git a/tf_fuzz/assets/crypto_asset.cpp b/tf_fuzz/assets/crypto_asset.cpp
new file mode 100644
index 0000000..7918a79
--- /dev/null
+++ b/tf_fuzz/assets/crypto_asset.cpp
@@ -0,0 +1,106 @@
+/*
+ * 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
+ gibberish *gib = new gibberish;
+ char buffer[256];
+ char *end;
+ int buf_len = 5ULL + (uint64_t) (rand() % 10);
+ end = gib->word (false, buffer, buffer + buf_len);
+ *end = '\0';
+ buffer[buf_len] = '\0';
+ handle_str = buffer;
+ // 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/tf_fuzz/assets/crypto_asset.hpp b/tf_fuzz/assets/crypto_asset.hpp
new file mode 100644
index 0000000..bcee450
--- /dev/null
+++ b/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:
+ key_policy_info policy;
+ // 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
+ // 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/tf_fuzz/assets/crypto_asset.o b/tf_fuzz/assets/crypto_asset.o
new file mode 100644
index 0000000..accb11f
--- /dev/null
+++ b/tf_fuzz/assets/crypto_asset.o
Binary files differ
diff --git a/tf_fuzz/assets/psa_asset.cpp b/tf_fuzz/assets/psa_asset.cpp
new file mode 100644
index 0000000..2c230e7
--- /dev/null
+++ b/tf_fuzz/assets/psa_asset.cpp
@@ -0,0 +1,55 @@
+/*
+ * 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_info.name_specified = true;
+ asset_name.assign (set_val);
+}
+
+string psa_asset::get_name (void)
+{
+ return asset_name;
+}
+
+bool psa_asset::simulate (void) {
+ return false;
+ // by default, assume that nothing changed; derived classes may override.
+}
+
+psa_asset::psa_asset (void) // (default constructor)
+{
+ asset_info.asset_ser_no = unique_id_counter++;
+}
+
+
+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/tf_fuzz/assets/psa_asset.hpp b/tf_fuzz/assets/psa_asset.hpp
new file mode 100644
index 0000000..9eb4d3f
--- /dev/null
+++ b/tf_fuzz/assets/psa_asset.hpp
@@ -0,0 +1,69 @@
+/*
+ * 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. */
+ expect_info exp_data;
+ /* For now at least, this is here only for its n_exp_vars member, to
+ keep track of how many expected-data variables in the test. */
+ asset_name_id_info asset_info; // everything about the asset(s) for this line
+ key_policy_info policy; // (specific to crypto, but have to put this here)
+ 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"
+ 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);
+ virtual bool simulate (void);
+ /* simulate() tells this asset to react to its current state information.
+ Initially, this won't really do much, but will allow assets to react
+ to each other, if that is relevant. It returns true if anything
+ in the state of the asset changed, in which case all assets' simulate()
+ methods will be invoked again to react again. That will repeat until
+ all assets read a quiescent state. */
+ 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/tf_fuzz/assets/psa_asset.o b/tf_fuzz/assets/psa_asset.o
new file mode 100644
index 0000000..994bdd7
--- /dev/null
+++ b/tf_fuzz/assets/psa_asset.o
Binary files differ
diff --git a/tf_fuzz/assets/sst_asset.cpp b/tf_fuzz/assets/sst_asset.cpp
new file mode 100644
index 0000000..ac4de6f
--- /dev/null
+++ b/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_info.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/tf_fuzz/assets/sst_asset.hpp b/tf_fuzz/assets/sst_asset.hpp
new file mode 100644
index 0000000..0fbd5b8
--- /dev/null
+++ b/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/tf_fuzz/assets/sst_asset.o b/tf_fuzz/assets/sst_asset.o
new file mode 100644
index 0000000..2e5a2ef
--- /dev/null
+++ b/tf_fuzz/assets/sst_asset.o
Binary files differ
diff --git a/tf_fuzz/boilerplate/README b/tf_fuzz/boilerplate/README
new file mode 100644
index 0000000..60c78fa
--- /dev/null
+++ b/tf_fuzz/boilerplate/README
@@ -0,0 +1,10 @@
+These are the C++ code to work with the customizable, "boilerplate" code
+snippets in the .../lib directory.
+
+For more information, please browse to:
+
+ https://ci.trustedfirmware.org/job/tf-m-build-test-nightly/lastSuccessfulBuild/artifact/build-docs/tf-m_documents/install/doc/user_guide/html/docs/user_guides/tf_fuzz/boilerplate_dir.html
+
+--------------
+
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
diff --git a/tf_fuzz/boilerplate/boilerplate.cpp b/tf_fuzz/boilerplate/boilerplate.cpp
new file mode 100644
index 0000000..60deab7
--- /dev/null
+++ b/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/tf_fuzz/boilerplate/boilerplate.hpp b/tf_fuzz/boilerplate/boilerplate.hpp
new file mode 100644
index 0000000..4bbf651
--- /dev/null
+++ b/tf_fuzz/boilerplate/boilerplate.hpp
@@ -0,0 +1,268 @@
+/*
+ * 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 */
+ preamble_C = 3, // setup stuff before PSA calls begin
+ /* Strings to be substituted from template:
+ $purpose: The purpose of the test */
+ declare_int = 4, // declaration for an int
+ /* Strings to be substituted from template:
+ $var: The integer thing to declare
+ $init: Its initialization */
+ declare_string = 5, // declaration for a string
+ /* Strings to be substituted from template:
+ $var: The string variable to declare
+ $init: Its initialization */
+ declare_big_string = 6, // declaration for a string, sized large
+ /* Strings to be substituted from template:
+ $var: The string variable to declare
+ $init: Its initialization */
+ declare_size_t = 7, // declaration for a size_t
+ /* Strings to be substituted from template:
+ $var: The integer thing to declare
+ $init: Its initialization */
+ declare_policy = 8, // declaration for a policy (key attributes)
+ /* Strings to be substituted from template:
+ $var: The variable to declare */
+ declare_policy_algorithm = 9, // declaration for a
+ /* Strings to be substituted from template:
+ $var: The variable to declare */
+ declare_policy_lifetime = 10, // declaration for a
+ /* Strings to be substituted from template:
+ $var: The variable to declare */
+ declare_policy_type = 11, // declaration for a
+ /* Strings to be substituted from template:
+ $var: The variable to declare */
+ declare_policy_usage = 12, // declaration for a
+ /* Strings to be substituted from template:
+ $var: The variable to declare */
+ declare_key = 13, // declaration for a
+ /* Strings to be substituted from template:
+ $var: The variable to declare */
+ declare_generic = 14, // 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 = 15, // print a message to the test log
+ /* Strings to be substituted from template:
+ $message: What to print. */
+ teardown_sst = 16, // call to delete SST resources after test completes
+ /* Strings to be substituted from template:
+ $uid: (Exactly that) */
+ teardown_sst_check = 17, // boilerplate code to check success of previous;
+ /* No strings to be substituted from template */
+ teardown_key = 18, // call to delete crypto keys after test completes
+ /* Strings to be substituted from template:
+ $handle: The handle to the key */
+ teardown_key_check = 19, // boilerplate code to check success of previous;
+ /* No strings to be substituted from template */
+ closeout = 20, // final code to close out the test.
+ // No strings to substitute.
+ sst_pass_string = 21, // passing SST expected result
+ sst_fail_removed = 22, // SST expected result from having deleted the asset
+ // SST calls:
+ set_sst_call = 23, // 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 = 24, // boilerplate code to check success of previous;
+ /* Strings to be substituted from template:
+ $expect: Expected return status string */
+ get_sst_call = 25, // 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 = 26, // boilerplate code to check call result only;
+ /* Strings to be substituted from template:
+ $expect: Expected return status string */
+ get_sst_check_all = 27, // 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 = 28, // 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 = 29, // boilerplate for removing an SST asset;
+ /* Strings to be substituted from template:
+ $uid: (Exactly that) */
+ remove_sst_check = 30, // boilerplate code to check success of previous;
+ /* Strings to be substituted from template:
+ $expect: Expected return status */
+ // Crypto-key-policy calls:
+ init_policy = 31, // initialize a policy (key attributes);
+ /* Strings to be substituted from template:
+ $policy: The name of the policy */
+ reset_policy = 32, // reset a policy (key attributes);
+ /* Strings to be substituted from template:
+ $policy: The name of the policy */
+ add_policy_usage = 33, // add a usage flag to a policy;
+ /* Strings to be substituted from template:
+ $policy: The name of the policy
+ $flag: usage-flag name */
+ set_policy_lifetime = 34,
+ /* Strings to be substituted from template:
+ $policy: The name of the policy
+ $life: Lifetime -- volatile or persistent */
+ set_policy_size = 35,
+ /* Strings to be substituted from template:
+ $policy: The name of the policy
+ $size: The key size, in bits */
+ set_policy_type = 36,
+ /* Strings to be substituted from template:
+ $policy: The name of the policy
+ $type: The key type -- RSA pair, AES, etc. */
+ set_policy_algorithm = 37,
+ /* Strings to be substituted from template:
+ $policy: The name of the policy
+ $algorithm: The algorithm -- AEAD, sign, hash mask, etc. */
+ set_policy_usage = 38,
+ /* Strings to be substituted from template:
+ $policy: The name of the policy
+ $usage: The usage -- encrypt, decrypt, export, copy, etc. */
+ get_policy_lifetime = 39,
+ /* Strings to be substituted from template:
+ $policy: The name of the policy
+ $life: Lifetime -- volatile or persistent */
+ get_policy_lifetime_print = 40,
+ /* Strings to be substituted from template:
+ $policy: The name of the policy
+ $life: Lifetime -- volatile or persistent */
+ get_policy_size = 41,
+ /* Strings to be substituted from template:
+ $policy: The name of the policy
+ $size: The key size, in bits */
+ get_policy_type = 42,
+ /* Strings to be substituted from template:
+ $policy: The name of the policy
+ $type: The key type -- RSA pair, AES, etc. */
+ get_policy_type_print = 43,
+ /* Strings to be substituted from template:
+ $policy: The name of the policy
+ $type: The key type -- RSA pair, AES, etc. */
+ get_policy_algorithm = 44,
+ /* Strings to be substituted from template:
+ $policy: The name of the policy
+ $algorithm: The algorithm -- AEAD, sign, hash mask, etc. */
+ get_policy_algorithm_print = 45,
+ /* Strings to be substituted from template:
+ $policy: The name of the policy
+ $algorithm: The algorithm -- AEAD, sign, hash mask, etc. */
+ get_policy_usage = 46,
+ /* Strings to be substituted from template:
+ $policy: The name of the policy
+ $usage: The usage -- encrypt, decrypt, export, copy, etc. */
+ print_policy_usage = 47,
+ /* Strings to be substituted from template:
+ $policy: The name of the policy
+ $usage: The usage -- encrypt, decrypt, export, copy, etc. */
+ get_policy = 48, // read the policy from a key;
+ /* Strings to be substituted from template:
+ $key: The key whose policy we want to read
+ $policy: The policy variable to read into */
+ get_policy_check = 49, // success check fpr previous;
+ /* Strings to be substituted from template:
+ $expect: Expected return status */
+ // Crypto-key-related calls:
+ generate_key = 50, // generate key from scratch;
+ /* Strings to be substituted from template:
+ $key: The key to generate
+ $policy: The name of the policy */
+ generate_key_check = 51, // success check for previous;
+ /* Strings to be substituted from template:
+ $expect: Expected return status */
+ create_key = 52, // Create key from policy and key data;
+ /* Strings to be substituted from template:
+ $policy: The name of the policy
+ $data: The key data
+ $length: The key-data length -- sizeof() */
+ create_key_check = 53, // success check for previous;
+ /* Strings to be substituted from template:
+ $expect: Expected return status */
+ copy_key = 54, // Copy key data from one key to another; different policy;
+ /* Strings to be substituted from template:
+ $master: The source key-handle variable
+ $policy: The name of the policy
+ $copy: The copy key-handle variable */
+ copy_key_check = 55, // success check for previous;
+ /* Strings to be substituted from template:
+ $expect: Expected return status */
+ compare_data = 56, // compare data blocks, such as key data
+ /* Strings to be substituted from template:
+ $exp_data: Expected read data
+ $act_data: Actual read data
+ $length: Data length */
+ read_key_data = 57, // read key data;
+ /* Strings to be substituted from template:
+ $key: The key to read
+ $data: Where to put the data
+ $length: Length of the data buffer
+ $act_size: The actual size of the key data retrieved */
+ read_key_data_check = 58, // success check for previous;
+ /* Strings to be substituted from template:
+ $expect: Expected return status */
+ remove_key = 59, // boilerplate for creating a key;
+ /* Strings to be substituted from template:
+ $handle: The handle to the key */
+ remove_key_check = 60, // 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 = 61;
+
+
+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/tf_fuzz/boilerplate/boilerplate.o b/tf_fuzz/boilerplate/boilerplate.o
new file mode 100644
index 0000000..7de9b1b
--- /dev/null
+++ b/tf_fuzz/boilerplate/boilerplate.o
Binary files differ
diff --git a/tf_fuzz/calls/README b/tf_fuzz/calls/README
new file mode 100644
index 0000000..c57499e
--- /dev/null
+++ b/tf_fuzz/calls/README
@@ -0,0 +1,10 @@
+These classes define objects that describe everything needed to generate a PSA
+call.
+
+For more information, please browse to:
+
+ https://ci.trustedfirmware.org/job/tf-m-build-test-nightly/lastSuccessfulBuild/artifact/build-docs/tf-m_documents/install/doc/user_guide/html/docs/user_guides/tf_fuzz/calls_dir.html
+
+--------------
+
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
diff --git a/tf_fuzz/calls/crypto_call.cpp b/tf_fuzz/calls/crypto_call.cpp
new file mode 100644
index 0000000..85d7ac0
--- /dev/null
+++ b/tf_fuzz/calls/crypto_call.cpp
@@ -0,0 +1,1385 @@
+/*
+ * 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 "variables.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:
+**********************************************************************************/
+
+/* Most of the policy classes, in their fill_in_prep_code() method, need to ensure
+ that, at a minimum, the policy variable (psa_key_attributes_t) exists, so, just
+ to cut down code duplication: */
+void policy_call::policy_fill_in_prep_code (void)
+{
+ vector<variable_info>::iterator policy_variable;
+
+ policy_variable = test_state->find_var (asset_info.get_name());
+ if (policy_variable == test_state->variable.end()) {
+ // No such variable exists, so:
+ test_state->make_var (asset_info.get_name());
+ policy_variable = test_state->find_var (asset_info.get_name());
+ prep_code.assign (test_state->bplate->bplate_string[declare_policy]);
+ find_replace_1st ("$var", asset_info.get_name(), prep_code);
+ }
+}
+
+
+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)
+{
+ // Note: Key attributes are set in the key_policy_info constructor.
+}
+policy_call::~policy_call (void)
+{
+ // Nothing further to delete.
+ return; // just to have something to pin a breakpoint onto
+}
+
+vector<psa_asset*>::iterator policy_call::resolve_asset (bool create_asset_bool,
+ psa_asset_usage where) {
+ vector<psa_asset*>::iterator found_asset;
+ vector<psa_asset*> *asset_vector;
+ int asset_pick;
+
+ if (random_asset != psa_asset_usage::all) {
+ // != psa_asset_usage::all means to choose some known asset at random:
+ if (random_asset == psa_asset_usage::active) {
+ asset_vector = &(test_state->active_policy_asset);
+ asset_info.how_asset_found = asset_search::found_active;
+ } else if (random_asset == psa_asset_usage::deleted) {
+ asset_vector = &(test_state->deleted_policy_asset);
+ asset_info.how_asset_found = asset_search::found_deleted;
+ } else {
+ // "invalid" assets are not currently used.
+ cerr << "\nError: Tool-internal: Please report error 1102 to " << endl
+ << "TF-Fuzz developers."
+ << endl;
+ exit(1102);
+ }
+ if (asset_vector->size() > 0) {
+ /* Pick an active or deleted asset at random: */
+ asset_pick = rand() % asset_vector->size();
+ found_asset = asset_vector->begin() + asset_pick;
+ /* Copy asset information into template tracker: */
+ asset_info.id_n = (*found_asset)->asset_info.id_n;
+ asset_info.asset_ser_no
+ = (*found_asset)->asset_info.asset_ser_no;
+ } else {
+ if (random_asset == psa_asset_usage::active) {
+ cerr << "\nError: A policy call asks for a "
+ << "randomly chosen active asset, when none " << endl
+ << "is currently defined." << endl;
+ exit(1010);
+ } else if (random_asset == psa_asset_usage::deleted) {
+ cerr << "\nError: A policy call asks for a "
+ << "randomly chosen deleted asset, when none " << endl
+ << "is currently defined." << endl;
+ exit(1011);
+ } // "invalid" assets are not currently used.
+ }
+ } else {
+ // Find the asset by name:
+ asset_info.how_asset_found = test_state->find_or_create_policy_asset (
+ psa_asset_search::name, where,
+ asset_info.get_name(), 0, asset_info.asset_ser_no,
+ create_asset_bool, found_asset );
+ if ( asset_info.how_asset_found == asset_search::unsuccessful
+ || asset_info.how_asset_found == asset_search::something_wrong ) {
+ cerr << "\nError: Tool-internal: Please report error 108 to " << endl
+ << "TF-Fuzz developers."
+ << endl;
+ exit(108);
+ }
+ }
+ return found_asset;
+}
+
+/**********************************************************************************
+ 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)
+{
+ asset_info.the_asset = nullptr;
+}
+key_call::~key_call (void)
+{
+ // Nothing further to delete.
+ return; // just to have something to pin a breakpoint onto
+}
+
+vector<psa_asset*>::iterator key_call::resolve_asset (bool create_asset_bool,
+ psa_asset_usage where) {
+ vector<psa_asset*>::iterator found_asset;
+ vector<psa_asset*> *asset_vector;
+ int asset_pick;
+
+ if (random_asset != psa_asset_usage::all) {
+ // != psa_asset_usage::all means to choose some known asset at random:
+ if (random_asset == psa_asset_usage::active) {
+ asset_vector = &(test_state->active_key_asset);
+ asset_info.how_asset_found = asset_search::found_active;
+ } else if (random_asset == psa_asset_usage::deleted) {
+ asset_vector = &(test_state->deleted_key_asset);
+ asset_info.how_asset_found = asset_search::found_deleted;
+ } else {
+ // "invalid" assets are not currently used.
+ cerr << "\nError: Tool-internal: Please report error 1103 to " << endl
+ << "TF-Fuzz developers."
+ << endl;
+ exit(1103);
+ }
+ if (asset_vector->size() > 0) {
+ /* Pick an active or deleted asset at random: */
+ asset_pick = rand() % asset_vector->size();
+ found_asset = asset_vector->begin() + asset_pick;
+ /* Copy asset information into template tracker: */
+ asset_info.id_n = (*found_asset)->asset_info.id_n;
+ asset_info.asset_ser_no
+ = (*found_asset)->asset_info.asset_ser_no;
+ } else {
+ if (random_asset == psa_asset_usage::active) {
+ cerr << "\nError: A key call asks for a "
+ << "randomly chosen active asset, when none " << endl
+ << "is currently defined." << endl;
+ exit(1012);
+ } else if (random_asset == psa_asset_usage::deleted) {
+ cerr << "\nError: A key call asks for a "
+ << "randomly chosen deleted asset, when none " << endl
+ << "is currently defined." << endl;
+ exit(1013);
+ } // "invalid" assets are not currently used.
+ }
+ } else {
+ // Find the asset by name:
+ asset_info.how_asset_found = test_state->find_or_create_key_asset (
+ psa_asset_search::name, where,
+ asset_info.get_name(), 0, asset_info.asset_ser_no,
+ create_asset_bool, found_asset );
+ if ( asset_info.how_asset_found == asset_search::unsuccessful
+ || asset_info.how_asset_found == asset_search::something_wrong ) {
+ cerr << "\nError: Tool-internal: Please report error 108 to " << endl
+ << "TF-Fuzz developers."
+ << endl;
+ exit(108);
+ }
+ }
+ return found_asset;
+}
+
+/**********************************************************************************
+ End of methods of class key_call.
+**********************************************************************************/
+
+
+/**********************************************************************************
+ Methods of class init_policy_call follow:
+**********************************************************************************/
+
+init_policy_call::init_policy_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[init_policy]);
+ call_description = "initialize-policy call";
+}
+init_policy_call::~init_policy_call (void)
+{
+ return; // just to have something to pin a breakpoint onto
+}
+
+bool init_policy_call::copy_call_to_asset (void)
+{
+ return copy_call_to_asset_t<policy_asset*> (this, yes_create_asset);
+}
+
+void init_policy_call::fill_in_prep_code (void)
+{
+ policy_fill_in_prep_code();
+}
+
+void init_policy_call::fill_in_command (void)
+{
+ // (call_code already loaded by constructor)
+ find_replace_all ("$policy", asset_info.get_name(), call_code);
+ // Calculate the expected results:
+ calc_result_code();
+}
+
+/**********************************************************************************
+ End of methods of class init_policy_call.
+**********************************************************************************/
+
+
+/**********************************************************************************
+ Methods of class reset_policy_call follow:
+**********************************************************************************/
+
+reset_policy_call::reset_policy_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[reset_policy]);
+ call_description = "policy reset call";
+}
+reset_policy_call::~reset_policy_call (void)
+{
+ return; // just to have something to pin a breakpoint onto
+}
+
+bool reset_policy_call::copy_call_to_asset (void)
+{
+ return copy_call_to_asset_t<policy_asset*> (this, yes_create_asset);
+}
+
+void reset_policy_call::fill_in_prep_code (void)
+{
+ policy_fill_in_prep_code();
+}
+
+void reset_policy_call::fill_in_command (void)
+{
+ // (call_code already loaded by constructor)
+ find_replace_all ("$policy", asset_info.get_name(), call_code);
+ // Calculate the expected results:
+ calc_result_code();
+}
+
+/**********************************************************************************
+ End of methods of class reset_policy_call.
+**********************************************************************************/
+
+
+/**********************************************************************************
+ Methods of class add_policy_usage_call follow:
+**********************************************************************************/
+
+add_policy_usage_call::add_policy_usage_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[add_policy_usage]);
+ call_description = "policy add-usage call";
+}
+add_policy_usage_call::~add_policy_usage_call (void)
+{
+ return; // just to have something to pin a breakpoint onto
+}
+
+bool add_policy_usage_call::copy_call_to_asset (void)
+{
+ return copy_call_to_asset_t<policy_asset*> (this, yes_create_asset);
+}
+
+void add_policy_usage_call::fill_in_prep_code (void)
+{
+ policy_fill_in_prep_code();
+ /* TODO: The variable this creates should have been declared already. Should
+ this instead produce an error if it doesn't exist? */
+}
+
+void add_policy_usage_call::fill_in_command (void)
+{
+ // (call_code already loaded by constructor)
+ find_replace_all ("$policy", asset_info.get_name(), call_code);
+ find_replace_1st ("$flag", policy.usage_string, call_code);
+ // Calculate the expected results:
+ calc_result_code();
+}
+
+/**********************************************************************************
+ End of methods of class add_policy_usage_call.
+**********************************************************************************/
+
+
+/**********************************************************************************
+ Methods of class set_policy_lifetime_call follow:
+**********************************************************************************/
+
+set_policy_lifetime_call::set_policy_lifetime_call (tf_fuzz_info *test_state,
+ long &call_ser_no, // (constructor)
+ 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_lifetime]);
+ call_description = "policy lifetime-set call";
+}
+set_policy_lifetime_call::~set_policy_lifetime_call (void)
+{
+ return; // just to have something to pin a breakpoint onto
+}
+
+bool set_policy_lifetime_call::copy_call_to_asset (void)
+{
+ return copy_call_to_asset_t<policy_asset*> (this, yes_create_asset);
+}
+
+void set_policy_lifetime_call::fill_in_prep_code (void)
+{
+ policy_fill_in_prep_code();
+}
+
+void set_policy_lifetime_call::fill_in_command (void)
+{
+ // (call_code already loaded by constructor)
+ find_replace_all ("$policy", asset_info.get_name(), call_code);
+ find_replace_1st ("$life",
+ policy.persistent? "PSA_KEY_LIFETIME_PERSISTENT"
+ : "PSA_KEY_LIFETIME_VOLATILE",
+ call_code);
+ // Calculate the expected results:
+ calc_result_code();
+}
+
+/**********************************************************************************
+ End of methods of class set_policy_lifetime_call.
+**********************************************************************************/
+
+
+/**********************************************************************************
+ Methods of class set_policy_size_call follow:
+**********************************************************************************/
+
+set_policy_size_call::set_policy_size_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_size]);
+ call_description = "policy size-set call";
+}
+set_policy_size_call::~set_policy_size_call (void)
+{
+ return; // just to have something to pin a breakpoint onto
+}
+
+bool set_policy_size_call::copy_call_to_asset (void)
+{
+ return copy_call_to_asset_t<policy_asset*> (this, yes_create_asset);
+}
+
+void set_policy_size_call::fill_in_prep_code (void)
+{
+ policy_fill_in_prep_code();
+}
+
+void set_policy_size_call::fill_in_command (void)
+{
+ // (call_code already loaded by constructor)
+ find_replace_all ("$policy", asset_info.get_name(), call_code);
+ find_replace_1st ("$size", to_string (policy.n_bits), call_code);
+ // Calculate the expected results:
+ calc_result_code();
+}
+
+/**********************************************************************************
+ End of methods of class set_policy_size_call.
+**********************************************************************************/
+
+
+/**********************************************************************************
+ Methods of class set_policy_type_call follow:
+**********************************************************************************/
+
+set_policy_type_call::set_policy_type_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_type]);
+ call_description = "policy type-set call";
+}
+set_policy_type_call::~set_policy_type_call (void)
+{
+ return; // just to have something to pin a breakpoint onto
+}
+
+bool set_policy_type_call::copy_call_to_asset (void)
+{
+ return copy_call_to_asset_t<policy_asset*> (this, yes_create_asset);
+}
+
+void set_policy_type_call::fill_in_prep_code (void)
+{
+ policy_fill_in_prep_code();
+}
+
+void set_policy_type_call::fill_in_command (void)
+{
+ // (call_code already loaded by constructor)
+ find_replace_all ("$policy", asset_info.get_name(), call_code);
+ find_replace_1st ("$type", policy.key_type, call_code);
+ // Calculate the expected results:
+ calc_result_code();
+}
+
+/**********************************************************************************
+ End of methods of class set_policy_type_call.
+**********************************************************************************/
+
+
+/**********************************************************************************
+ Methods of class set_policy_algorithm_call follow:
+**********************************************************************************/
+
+set_policy_algorithm_call::set_policy_algorithm_call (tf_fuzz_info *test_state,
+ long &call_ser_no, // (constructor)
+ 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_algorithm]);
+ call_description = "policy algorithm-set call";
+}
+set_policy_algorithm_call::~set_policy_algorithm_call (void)
+{
+ return; // just to have something to pin a breakpoint onto
+}
+
+bool set_policy_algorithm_call::copy_call_to_asset (void)
+{
+ return copy_call_to_asset_t<policy_asset*> (this, yes_create_asset);
+}
+
+void set_policy_algorithm_call::fill_in_prep_code (void)
+{
+ policy_fill_in_prep_code();
+}
+
+void set_policy_algorithm_call::fill_in_command (void)
+{
+ // (call_code already loaded by constructor)
+ find_replace_all ("$policy", asset_info.get_name(), call_code);
+ find_replace_1st ("$algorithm", policy.key_algorithm, call_code);
+ // Calculate the expected results:
+ calc_result_code();
+}
+
+/**********************************************************************************
+ End of methods of class set_policy_algorithm_call.
+**********************************************************************************/
+
+
+/**********************************************************************************
+ Methods of class set_policy_usage_call follow:
+**********************************************************************************/
+
+set_policy_usage_call::set_policy_usage_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_usage]);
+ call_description = "policy usage-set call";
+}
+set_policy_usage_call::~set_policy_usage_call (void)
+{
+ return; // just to have something to pin a breakpoint onto
+}
+
+bool set_policy_usage_call::copy_call_to_asset (void)
+{
+ return copy_call_to_asset_t<policy_asset*> (this, yes_create_asset);
+}
+
+void set_policy_usage_call::fill_in_prep_code (void)
+{
+ policy_fill_in_prep_code();
+}
+
+void set_policy_usage_call::fill_in_command (void)
+{
+ find_replace_1st ("$policy", asset_info.get_name(), call_code);
+ find_replace_1st ("$usage", "0", call_code);
+ // Calculate the expected results:
+ calc_result_code();
+}
+
+/**********************************************************************************
+ End of methods of class set_policy_usage_call.
+**********************************************************************************/
+
+
+/**********************************************************************************
+ Methods of class get_policy_lifetime_call follow:
+**********************************************************************************/
+
+get_policy_lifetime_call::get_policy_lifetime_call (tf_fuzz_info *test_state,
+ long &call_ser_no, // (constructor)
+ 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_lifetime]);
+ call_description = "policy lifetime-get call";
+}
+get_policy_lifetime_call::~get_policy_lifetime_call (void)
+{
+ return; // just to have something to pin a breakpoint onto
+}
+
+bool get_policy_lifetime_call::copy_call_to_asset (void)
+{
+ return copy_call_to_asset_t<policy_asset*> (this, dont_create_asset);
+}
+
+void get_policy_lifetime_call::fill_in_prep_code (void)
+{
+ string var_name = asset_info.get_name() + "_life";
+ vector<variable_info>::iterator assign_variable;
+
+ policy_fill_in_prep_code(); // make sure the policy variable itself is defined
+ assign_variable = test_state->find_var (var_name);
+ if (assign_variable == test_state->variable.end()) {
+ // No such variable exists, so:
+ test_state->make_var (var_name);
+ prep_code.append (test_state->bplate->bplate_string[declare_policy_lifetime]);
+ find_replace_all ("$var", var_name, prep_code);
+ }
+}
+
+void get_policy_lifetime_call::fill_in_command (void)
+{
+ // (call_code already loaded by constructor)
+ find_replace_all ("$policy", asset_info.get_name(), call_code);
+ find_replace_1st ("$life", asset_info.get_name() + "_life", call_code);
+ // Calculate the expected results:
+ calc_result_code();
+}
+
+/**********************************************************************************
+ End of methods of class get_policy_lifetime_call.
+**********************************************************************************/
+
+
+/**********************************************************************************
+ Methods of class get_policy_size_call follow:
+**********************************************************************************/
+
+get_policy_size_call::get_policy_size_call (tf_fuzz_info *test_state,
+ long &call_ser_no, // (constructor)
+ 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_size]);
+ call_description = "policy size-get call";
+}
+get_policy_size_call::~get_policy_size_call (void)
+{
+ return; // just to have something to pin a breakpoint onto
+}
+
+bool get_policy_size_call::copy_call_to_asset (void)
+{
+ return copy_call_to_asset_t<policy_asset*> (this, dont_create_asset);
+}
+
+void get_policy_size_call::fill_in_prep_code (void)
+{
+ string var_name = asset_info.get_name() + "_size";
+ vector<variable_info>::iterator assign_variable;
+
+ policy_fill_in_prep_code(); // make sure the policy variable itself is defined
+ assign_variable = test_state->find_var (var_name);
+ if (assign_variable == test_state->variable.end()) {
+ // No such variable exists, so:
+ test_state->make_var (var_name);
+ prep_code.append (test_state->bplate->bplate_string[declare_size_t]);
+ find_replace_all ("$var", var_name, prep_code);
+ find_replace_1st ("$init", to_string(exp_data.data.length()), prep_code);
+ }
+}
+
+void get_policy_size_call::fill_in_command (void)
+{
+ // (call_code already loaded by constructor)
+ find_replace_all ("$policy", asset_info.get_name(), call_code);
+ find_replace_1st ("$size", asset_info.get_name() + "_size", call_code);
+ // Calculate the expected results:
+ calc_result_code();
+}
+
+/**********************************************************************************
+ End of methods of class get_policy_size_call.
+**********************************************************************************/
+
+
+/**********************************************************************************
+ Methods of class get_policy_type_call follow:
+**********************************************************************************/
+
+get_policy_type_call::get_policy_type_call (tf_fuzz_info *test_state,
+ long &call_ser_no, // (constructor)
+ 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_type]);
+ call_description = "policy type-get call";
+}
+get_policy_type_call::~get_policy_type_call (void)
+{
+ return; // just to have something to pin a breakpoint onto
+}
+
+bool get_policy_type_call::copy_call_to_asset (void)
+{
+ return copy_call_to_asset_t<policy_asset*> (this, dont_create_asset);
+}
+
+void get_policy_type_call::fill_in_prep_code (void)
+{
+ string var_name = asset_info.get_name() + "_type";
+ vector<variable_info>::iterator assign_variable;
+
+ policy_fill_in_prep_code(); // make sure the policy variable itself is defined
+ assign_variable = test_state->find_var (var_name);
+ if (assign_variable == test_state->variable.end()) {
+ // No such variable exists, so:
+ test_state->make_var (var_name);
+ prep_code.append (test_state->bplate->bplate_string[declare_policy_type]);
+ find_replace_all ("$var", var_name, prep_code);
+ }
+}
+
+void get_policy_type_call::fill_in_command (void)
+{
+ // (call_code already loaded by constructor)
+ find_replace_all ("$policy", asset_info.get_name(), call_code);
+ find_replace_1st ("$type", asset_info.get_name() + "_type", call_code);
+ // Calculate the expected results:
+ calc_result_code();
+}
+
+/**********************************************************************************
+ End of methods of class get_policy_type_call.
+**********************************************************************************/
+
+
+/**********************************************************************************
+ Methods of class get_policy_algorithm_call follow:
+**********************************************************************************/
+
+get_policy_algorithm_call::get_policy_algorithm_call (tf_fuzz_info *test_state,
+ long &call_ser_no, // (constructor)
+ 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_algorithm]);
+ call_description = "policy algorithm-get call";
+}
+get_policy_algorithm_call::~get_policy_algorithm_call (void)
+{
+ return; // just to have something to pin a breakpoint onto
+}
+
+bool get_policy_algorithm_call::copy_call_to_asset (void)
+{
+ return copy_call_to_asset_t<policy_asset*> (this, dont_create_asset);
+}
+
+void get_policy_algorithm_call::fill_in_prep_code (void)
+{
+ string var_name = asset_info.get_name() + "_algo";
+ vector<variable_info>::iterator assign_variable;
+
+ policy_fill_in_prep_code(); // make sure the policy variable itself is defined
+ assign_variable = test_state->find_var (var_name);
+ if (assign_variable == test_state->variable.end()) {
+ // No such variable exists, so:
+ test_state->make_var (var_name);
+ prep_code.append (test_state->bplate->bplate_string[declare_policy_algorithm]);
+ find_replace_all ("$var", var_name, prep_code);
+ }
+}
+
+void get_policy_algorithm_call::fill_in_command (void)
+{
+ // (call_code already loaded by constructor)
+ find_replace_all ("$policy", asset_info.get_name(), call_code);
+ find_replace_1st ("$algorithm", asset_info.get_name() + "_algo", call_code);
+ // Calculate the expected results:
+ calc_result_code();
+}
+
+/**********************************************************************************
+ End of methods of class get_policy_algorithm_call.
+**********************************************************************************/
+
+
+/**********************************************************************************
+ Methods of class get_policy_usage_call follow:
+**********************************************************************************/
+
+get_policy_usage_call::get_policy_usage_call (tf_fuzz_info *test_state,
+ long &call_ser_no, // (constructor)
+ 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_usage]);
+ call_description = "policy usage-get call";
+}
+get_policy_usage_call::~get_policy_usage_call (void)
+{
+ return; // just to have something to pin a breakpoint onto
+}
+
+bool get_policy_usage_call::copy_call_to_asset (void)
+{
+ return copy_call_to_asset_t<policy_asset*> (this, dont_create_asset);
+}
+
+void get_policy_usage_call::fill_in_prep_code (void)
+{
+ string var_name = asset_info.get_name() + "_usage";
+ vector<variable_info>::iterator assign_variable;
+
+ policy_fill_in_prep_code(); // make sure the policy variable itself is defined
+ assign_variable = test_state->find_var (var_name);
+ if (assign_variable == test_state->variable.end()) {
+ // No such variable exists, so:
+ test_state->make_var (var_name);
+ prep_code.append (test_state->bplate->bplate_string[declare_policy_usage]);
+ find_replace_all ("$var", var_name, prep_code);
+ }
+}
+
+void get_policy_usage_call::fill_in_command (void)
+{
+ // (call_code already loaded by constructor)
+ find_replace_all ("$policy", asset_info.get_name(), call_code);
+ find_replace_1st ("$usage", asset_info.get_name() + "_usage", call_code);
+ // Calculate the expected results:
+ calc_result_code();
+}
+
+/**********************************************************************************
+ End of methods of class get_policy_usage_call.
+**********************************************************************************/
+
+
+/**********************************************************************************
+ Methods of class print_policy_usage_call follow:
+**********************************************************************************/
+
+print_policy_usage_call::print_policy_usage_call (tf_fuzz_info *test_state,
+ long &call_ser_no, // (constructor)
+ 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[print_policy_usage]);
+ call_description = "policy usage-print call";
+}
+print_policy_usage_call::~print_policy_usage_call (void)
+{
+ return; // just to have something to pin a breakpoint onto
+}
+
+bool print_policy_usage_call::copy_call_to_asset (void)
+{
+ return copy_call_to_asset_t<policy_asset*> (this, dont_create_asset);
+}
+
+void print_policy_usage_call::fill_in_prep_code (void)
+{
+ string var_name = asset_info.get_name() + "_usage";
+ vector<variable_info>::iterator assign_variable;
+
+ policy_fill_in_prep_code(); // make sure the policy variable itself is defined
+ // Make sure policy-usage variable is defined:
+ assign_variable = test_state->find_var (var_name);
+ if (assign_variable == test_state->variable.end()) {
+ // No such variable exists, so:
+ test_state->make_var (var_name);
+ prep_code.append (test_state->bplate->bplate_string[declare_policy_usage]);
+ find_replace_all ("$var", var_name, prep_code);
+ }
+}
+
+void print_policy_usage_call::fill_in_command (void)
+{
+ string var_name = asset_info.get_name() + "_usage";
+
+ // (call_code already loaded by constructor)
+ find_replace_all ("$policy", asset_info.get_name(), call_code);
+ find_replace_1st ("$usage_string", policy.usage_string, call_code);
+ find_replace_1st ("$usage", var_name, call_code);
+ find_replace_1st ("$print_usage_true_string", policy.print_usage_true_string,
+ call_code);
+ find_replace_1st ("$print_usage_false_string", policy.print_usage_false_string,
+ call_code);
+ // Calculate the expected results:
+ calc_result_code();
+}
+
+/**********************************************************************************
+ End of methods of class print_policy_usage_call.
+**********************************************************************************/
+
+
+/**********************************************************************************
+ Methods of class get_key_policy_call follow:
+**********************************************************************************/
+
+get_key_policy_call::get_key_policy_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]);
+ call_description = "policy get call";
+}
+get_key_policy_call::~get_key_policy_call (void)
+{
+ return; // just to have something to pin a breakpoint onto
+}
+
+bool get_key_policy_call::copy_call_to_asset (void)
+{
+ return copy_call_to_asset_t<key_asset*> (this, dont_create_asset);
+}
+
+void get_key_policy_call::fill_in_prep_code (void)
+{
+ // No prep code required.
+ return; // just to have something to pin a breakpoint onto
+}
+
+void get_key_policy_call::fill_in_command (void)
+{
+ // (call_code already loaded by constructor)
+ find_replace_all ("key", asset_info.get_name(), call_code);
+ find_replace_all ("$policy", policy.asset_2_name, call_code);
+ // Calculate the expected results:
+ calc_result_code();
+}
+
+/**********************************************************************************
+ End of methods of class get_key_policy_call.
+**********************************************************************************/
+
+
+/**********************************************************************************
+ Methods of class generate_key_call follow:
+**********************************************************************************/
+
+generate_key_call::generate_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[generate_key]);
+ check_code.assign (test_state->bplate->bplate_string[generate_key_check]);
+ call_description = "key-generate call";
+}
+generate_key_call::~generate_key_call (void)
+{
+ return; // just to have something to pin a breakpoint onto
+}
+
+bool generate_key_call::copy_call_to_asset (void)
+{
+ return copy_call_to_asset_t<key_asset*> (this, yes_create_asset);
+}
+
+void generate_key_call::fill_in_prep_code (void)
+{
+ string var_name = asset_info.get_name();
+ vector<variable_info>::iterator assign_variable;
+
+ // Make sure key variable is defined:
+ assign_variable = test_state->find_var (var_name);
+ if (assign_variable == test_state->variable.end()) {
+ // No such variable exists, so:
+ test_state->make_var (var_name);
+ prep_code.append (test_state->bplate->bplate_string[declare_key]);
+ find_replace_all ("$var", var_name, prep_code);
+ }
+}
+
+void generate_key_call::fill_in_command (void)
+{
+ // (call_code already loaded by constructor)
+ find_replace_all ("$policy", policy.asset_2_name, call_code);
+ find_replace_all ("$key", asset_info.get_name(), call_code);
+ // Calculate the expected results:
+ calc_result_code();
+}
+
+/**********************************************************************************
+ End of methods of class generate_key_call.
+**********************************************************************************/
+
+
+/**********************************************************************************
+ Methods of class create_key_call follow:
+**********************************************************************************/
+
+create_key_call::create_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[create_key]);
+ check_code.assign (test_state->bplate->bplate_string[create_key_check]);
+ call_description = "key-create call";
+}
+create_key_call::~create_key_call (void)
+{
+ return; // just to have something to pin a breakpoint onto
+}
+
+bool create_key_call::copy_call_to_asset (void)
+{
+ return copy_call_to_asset_t<key_asset*> (this, yes_create_asset);
+}
+
+void create_key_call::fill_in_prep_code (void)
+{
+ string var_name = asset_info.get_name();
+ vector<variable_info>::iterator assign_variable;
+ gibberish gib;
+ char gib_buff[500];
+ string t_string;
+
+ // Key variable:
+ assign_variable = test_state->find_var (var_name);
+ if (assign_variable == test_state->variable.end()) {
+ // No such variable exists, so:
+ test_state->make_var (var_name);
+ prep_code.append (test_state->bplate->bplate_string[declare_key]);
+ find_replace_all ("$var", var_name, prep_code);
+ }
+ // Key-data variable:
+ var_name = asset_info.get_name() + "_set_data";
+ assign_variable = test_state->find_var (var_name);
+ if (assign_variable == test_state->variable.end()) {
+ // No such variable exists, so:
+ test_state->make_var (var_name);
+ prep_code.append (test_state->bplate->bplate_string[declare_big_string]);
+ find_replace_all ("$var", var_name, prep_code);
+ int rand_data_length = 12 + (rand() % 100);
+ gib.sentence (gib_buff, gib_buff + rand_data_length - 1);
+ t_string = gib_buff;
+ find_replace_all ("$init", t_string, prep_code);
+ }
+}
+
+void create_key_call::fill_in_command (void)
+{
+ // (call_code already loaded by constructor)
+ find_replace_all ("$policy", policy.asset_2_name, call_code);
+ find_replace_all ("$data", asset_info.get_name() + "_set_data", call_code);
+ find_replace_all ("$length", to_string (policy.n_bits), call_code);
+ find_replace_all ("$key", asset_info.get_name(), call_code);
+ // Calculate the expected results:
+ calc_result_code();
+}
+
+/**********************************************************************************
+ End of methods of class create_key_call.
+**********************************************************************************/
+
+
+/**********************************************************************************
+ Methods of class copy_key_call follow:
+**********************************************************************************/
+
+copy_key_call::copy_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[copy_key]);
+ check_code.assign (test_state->bplate->bplate_string[copy_key_check]);
+ call_description = "key-copy call";
+}
+copy_key_call::~copy_key_call (void)
+{
+ return; // just to have something to pin a breakpoint onto
+}
+
+bool copy_key_call::copy_call_to_asset (void)
+{
+ return copy_call_to_asset_t<key_asset*> (this, yes_create_asset);
+}
+
+void copy_key_call::fill_in_prep_code (void)
+{
+ string var_name = asset_info.get_name();
+ vector<variable_info>::iterator assign_variable;
+
+ // Make sure key variable is defined:
+ assign_variable = test_state->find_var (var_name);
+ if (assign_variable == test_state->variable.end()) {
+ // No such variable exists, so:
+ test_state->make_var (var_name);
+ prep_code.append (test_state->bplate->bplate_string[declare_key]);
+ find_replace_all ("$var", var_name, prep_code);
+ }
+}
+
+void copy_key_call::fill_in_command (void)
+{
+ vector<psa_asset*>::iterator key_asset;
+ vector<psa_asset*> *asset_vector;
+ int asset_pick;
+
+ // Calculate the expected results:
+ asset_search find_result;
+ vector<psa_asset*>::iterator asset;
+ long dummy = 0L;
+ // See if the source key does not exist:
+
+ if (random_asset != psa_asset_usage::all) {
+ // != psa_asset_usage::all means to choose some known asset at random:
+ if (random_asset == psa_asset_usage::active) {
+ asset_vector = &(test_state->active_key_asset);
+ find_result = asset_info.how_asset_found = asset_search::found_active;
+ // if empty, we'll error out, below.
+ } else if (random_asset == psa_asset_usage::deleted) {
+ asset_vector = &(test_state->deleted_key_asset);
+ find_result = asset_info.how_asset_found = asset_search::found_deleted;
+ } else {
+ // "invalid" assets are not currently used.
+ cerr << "\nError: Tool-internal: Please report error 1103 to " << endl
+ << "TF-Fuzz developers."
+ << endl;
+ exit(1103);
+ }
+ if (asset_vector->size() > 0) {
+ /* Pick an active or deleted asset at random: */
+ asset_pick = rand() % asset_vector->size();
+ key_asset = asset_vector->begin() + asset_pick;
+ /* Copy asset information into template tracker: */
+ asset_info.id_n = (*key_asset)->asset_info.id_n;
+ asset_info.asset_ser_no
+ = (*key_asset)->asset_info.asset_ser_no;
+ } else {
+ if (random_asset == psa_asset_usage::active) {
+ cerr << "\nError: A key call asks for a "
+ << "randomly chosen active asset, when none " << endl
+ << "is currently defined." << endl;
+ exit(1012);
+ } else if (random_asset == psa_asset_usage::deleted) {
+ cerr << "\nError: A key call asks for a "
+ << "randomly chosen deleted asset, when none " << endl
+ << "is currently defined." << endl;
+ exit(1013);
+ } // "invalid" assets are not currently used.
+ }
+ } else {
+ find_result = test_state->
+ find_or_create_key_asset (psa_asset_search::name, psa_asset_usage::active,
+ policy.asset_3_name, (uint64_t) 0, dummy,
+ dont_create_asset, key_asset);
+ }
+ if (find_result != asset_search::found_active) {
+ exp_data.pf_specified = true;
+ exp_data.pf_result_string = "PSA_ERROR_INVALID_ARGUMENT";
+ // TODO: Pull this in from boilerplate file
+ } else {
+ // See if the new policy does not exist:
+ find_result = test_state->
+ find_or_create_policy_asset (psa_asset_search::name, psa_asset_usage::active,
+ policy.asset_2_name, (uint64_t) 0, dummy,
+ dont_create_asset, asset);
+ if (find_result != asset_search::found_active) {
+ exp_data.pf_specified = true;
+ exp_data.pf_result_string = "PSA_ERROR_INVALID_ARGUMENT";
+ // TODO: Pull this in from boilerplate file
+ } else if (!(*asset)->policy.copyable) {
+ // See if the source key does not support export:
+ // TODO: Or wait, it's the original policy for the key, right?
+ exp_data.pf_specified = true;
+ exp_data.pf_result_string = "PSA_ERROR_NOT_PERMITTED";
+ }
+ }
+
+ // (call_code already loaded by constructor)
+ find_replace_all ("$master", (*key_asset)->asset_info.get_name(), call_code);
+ find_replace_all ("$policy", policy.asset_2_name, call_code);
+ find_replace_all ("$copy", asset_info.get_name(), call_code);
+ calc_result_code();
+}
+
+/**********************************************************************************
+ End of methods of class copy_key_call.
+**********************************************************************************/
+
+
+/**********************************************************************************
+ Methods of class read_key_data_call follow:
+**********************************************************************************/
+
+read_key_data_call::read_key_data_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[read_key_data]);
+ check_code.assign (test_state->bplate->bplate_string[read_key_data_check]);
+ call_description = "key read-data call";
+}
+read_key_data_call::~read_key_data_call (void)
+{
+ return; // just to have something to pin a breakpoint onto
+}
+
+bool read_key_data_call::copy_call_to_asset (void)
+{
+ return copy_call_to_asset_t<key_asset*> (this, dont_create_asset);
+}
+
+void read_key_data_call::fill_in_prep_code (void)
+{
+ string var_name, length_var_name, actual_length_var_name, var_name_suffix,
+ length_var_name_suffix, temp_string;
+ vector<variable_info>::iterator expect_variable;
+ vector<variable_info>::iterator assign_variable;
+
+ if (exp_data.data_var_specified) {
+ var_name.assign (exp_data.data_var + "_data");
+ length_var_name.assign (exp_data.data_var + "_length");
+ /* If actual-data variable doesn't already exist, create variable tracker,
+ and write declaration for it: */
+ expect_variable = test_state->find_var (exp_data.data_var);
+ if (expect_variable == test_state->variable.end()) {
+ // No such variable exists, so:
+ test_state->make_var (exp_data.data_var);
+ expect_variable = test_state->find_var (exp_data.data_var);
+ prep_code.append (test_state->bplate->bplate_string[declare_big_string]);
+ find_replace_1st ("$var", var_name, prep_code);
+ temp_string = (char *) expect_variable->value;
+ find_replace_1st ("$init", temp_string, prep_code);
+ // Input data length:
+ prep_code.append (test_state->bplate->bplate_string[declare_size_t]);
+ find_replace_1st ("$var", length_var_name, prep_code);
+ find_replace_1st ("$init", to_string(temp_string.length()), prep_code);
+ // TODO: Is these lengths in bits or bytes?
+ }
+ }
+ // else we're not comparing to named variable, so compare to assigned data.
+ // Actual (output) data length:
+ if (assign_data_var_specified) {
+ var_name.assign (assign_data_var + "_data");
+ length_var_name.assign (assign_data_var + "_length");
+ actual_length_var_name.assign (assign_data_var + "_act_length");
+ /* If actual-data variable doesn't already exist, create variable tracker,
+ and write declaration for it: */
+ assign_variable = test_state->find_var (assign_data_var);
+ if (assign_variable == test_state->variable.end()) {
+ // No such variable exists, so:
+ test_state->make_var (assign_data_var);
+ assign_variable = test_state->find_var (assign_data_var);
+ prep_code.append (test_state->bplate->bplate_string[declare_big_string]);
+ find_replace_1st ("$var", var_name, prep_code);
+ temp_string = (char *) assign_variable->value;
+ find_replace_1st ("$init", temp_string, prep_code);
+ // Input data length:
+ prep_code.append (test_state->bplate->bplate_string[declare_size_t]);
+ find_replace_1st ("$var", length_var_name, prep_code);
+ find_replace_1st ("$init", to_string(temp_string.length()), prep_code);
+ }
+ } else {
+ // Key data not read into a named variable, so use default C variable:
+ var_name = asset_info.get_name() + "_act_data";
+ prep_code.append (test_state->bplate->bplate_string[declare_string]);
+ find_replace_1st ("$var", var_name, prep_code);
+ find_replace_1st ("$init", set_data.get(), prep_code);
+ actual_length_var_name.assign (asset_info.get_name() + "_act_length");
+ prep_code.append (test_state->bplate->bplate_string[declare_size_t]);
+ find_replace_1st ("$var", actual_length_var_name, prep_code);
+ find_replace_1st ("$init", to_string(set_data.get().length()), prep_code);
+ }
+ length_var_name_suffix = "_read_length";
+ var_name.assign (asset_info.get_name() + var_name_suffix);
+ length_var_name.assign (asset_info.get_name() + length_var_name_suffix);
+ prep_code.append (test_state->bplate->bplate_string[declare_size_t]);
+ find_replace_1st ("$var", length_var_name, prep_code);
+ find_replace_1st ("$init", to_string(set_data.get().length()), prep_code);
+}
+
+void read_key_data_call::fill_in_command (void)
+{
+ string var_name, length_var_name, exp_var_name, exp_length_var_name,
+ actual_length_var_name, var_name_suffix, length_var_name_suffix,
+ temp_string;
+
+ // Fill in the PSA command itself:
+ actual_length_var_name.assign (asset_info.get_name() + "_read_length");
+ if (assign_data_var_specified) {
+ var_name.assign (assign_data_var + "_data");
+ length_var_name.assign (assign_data_var + "_length");
+ } else {
+ var_name_suffix = "_act_data";
+ var_name.assign (asset_info.get_name() + var_name_suffix);
+ length_var_name_suffix = "_act_length";
+ length_var_name.assign (asset_info.get_name() + length_var_name_suffix);
+ }
+ find_replace_1st ("$data", var_name, call_code);
+ find_replace_1st ("$key", asset_info.get_name(), call_code);
+ string id_string = to_string((long) asset_info.id_n++);
+ find_replace_1st ("$length", length_var_name, call_code);
+ find_replace_1st ("$act_size", actual_length_var_name, call_code);
+
+ // Check data:
+ if (exp_data.data_var_specified) {
+ check_code.assign (test_state->bplate->bplate_string[compare_data]);
+ exp_var_name.assign (exp_data.data_var + "_data");
+ exp_length_var_name.assign (exp_data.data_var + "_length");
+ find_replace_1st ("$act_data", var_name, check_code);
+ find_replace_1st ("$exp_data", exp_var_name, check_code);
+ find_replace_1st ("$length", exp_length_var_name, check_code);
+ }
+
+ // See if the source key did not exist:
+ if (!policy.exportable) {
+ // See if the source key does not support export:
+ exp_data.pf_specified = true;
+ exp_data.pf_result_string = "PSA_ERROR_NOT_PERMITTED";
+ }
+ calc_result_code();
+}
+
+/**********************************************************************************
+ End of methods of class read_key_data_call.
+**********************************************************************************/
+
+
+/**********************************************************************************
+ Methods of class remove_key_call follow:
+**********************************************************************************/
+
+remove_key_call::remove_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]);
+ call_description = "key-remove call";
+}
+remove_key_call::~remove_key_call (void)
+{
+ return; // just to have something to pin a breakpoint onto
+}
+
+bool remove_key_call::copy_call_to_asset (void)
+{
+ return copy_call_to_asset_t<key_asset*> (this, dont_create_asset);
+}
+
+void remove_key_call::fill_in_prep_code (void)
+{
+ // No prep code required.
+ return; // just to have something to pin a breakpoint onto
+}
+
+void remove_key_call::fill_in_command (void)
+{
+ // (call_code already loaded by constructor)
+ find_replace_all ("$key", asset_info.get_name(), call_code);
+ // Calculate the expected results:
+ calc_result_code();
+}
+
+/**********************************************************************************
+ End of methods of class remove_key_call.
+**********************************************************************************/
+
diff --git a/tf_fuzz/calls/crypto_call.hpp b/tf_fuzz/calls/crypto_call.hpp
new file mode 100644
index 0000000..7fd58cc
--- /dev/null
+++ b/tf_fuzz/calls/crypto_call.hpp
@@ -0,0 +1,582 @@
+/*
+ * 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"
+*/
+
+template<class T> bool copy_call_to_asset_t (psa_call *call, bool create_asset_bool)
+{
+ vector<psa_asset*>::iterator found_asset;
+
+ found_asset = call->resolve_asset (create_asset_bool, psa_asset_usage::all);
+ // Copy over everything relevant:
+ if (call->asset_info.how_asset_found != asset_search::not_found) {
+ call->asset_info.the_asset = reinterpret_cast<T>(*found_asset);
+ /* Note: The vector is base-class, but the assets in this list
+ themselves *really are* policy_asset-type objects. */
+ int i = call->asset_info.the_asset->set_data.n_set_vars; // save this
+ call->asset_info.the_asset->exp_data.data = call->exp_data.data;
+ call->asset_info.the_asset->set_data = call->set_data;
+ call->asset_info.the_asset->set_data.n_set_vars = call->set_data.n_set_vars = ++i;
+ call->asset_info.the_asset->policy = call->policy;
+ call->asset_info.the_asset->handle_str = call->asset_info.get_name();
+ if (call->asset_info.how_asset_found == asset_search::created_new) {
+ call->asset_info.the_asset->asset_info.name_specified
+ = call->asset_info.name_specified;
+ call->asset_info.the_asset->asset_info.set_name (call->asset_info.get_name());
+ call->asset_info.the_asset->asset_info.asset_ser_no
+ = call->asset_info.asset_ser_no;
+ call->asset_info.the_asset->asset_info.id_n = call->asset_info.id_n;
+ }
+ }
+ return true;
+}
+
+
+using namespace std;
+
+class policy_call : public crypto_call
+{
+public:
+ // Data members: // (low value in hiding these behind setters and getters)
+ // Methods:
+ vector<psa_asset*>::iterator resolve_asset (bool create_asset_bool,
+ psa_asset_usage where);
+ void policy_fill_in_prep_code (void);
+ 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)
+ // Methods:
+ vector<psa_asset*>::iterator resolve_asset (bool create_asset_bool,
+ psa_asset_usage where);
+ 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:
+};
+
+
+/**********************************************************************************
+ Derived classes of class policy_call follow:
+**********************************************************************************/
+
+
+class init_policy_call : public policy_call
+{
+public:
+ // Data members:
+ // Methods:
+ bool copy_call_to_asset (void);
+ void fill_in_prep_code (void);
+ void fill_in_command (void);
+ init_policy_call (tf_fuzz_info *test_state, long &asset_ser_no,
+ asset_search how_asset_found); // (constructor)
+ ~init_policy_call (void);
+
+
+protected:
+ // Data members:
+ // Methods:
+
+private:
+ // Data members:
+ // Methods:
+};
+
+
+class reset_policy_call : public policy_call
+{
+public:
+ // Data members:
+ // Methods:
+ bool copy_call_to_asset (void);
+ void fill_in_prep_code (void);
+ void fill_in_command (void);
+ reset_policy_call (tf_fuzz_info *test_state, long &asset_ser_no,
+ asset_search how_asset_found); // (constructor)
+ ~reset_policy_call (void);
+
+
+protected:
+ // Data members:
+ // Methods:
+
+private:
+ // Data members:
+ // Methods:
+};
+
+
+class set_policy_usage_call : public policy_call
+{
+public:
+ // Data members:
+ // Methods:
+ bool copy_call_to_asset (void);
+ void fill_in_prep_code (void);
+ void fill_in_command (void);
+ set_policy_usage_call (tf_fuzz_info *test_state, long &asset_ser_no,
+ asset_search how_asset_found); // (constructor)
+ ~set_policy_usage_call (void);
+
+
+protected:
+ // Data members:
+ // Methods:
+
+private:
+ // Data members:
+ // Methods:
+};
+
+
+/* set_policy_usage_call(), above, gives a policy particular attribute, and resets
+ all others. add_policy_usage_call(), below, ORs in an additional usage
+ attribute, to whatever is already in there. */
+
+class add_policy_usage_call : public policy_call
+{
+public:
+ // Data members:
+ // Methods:
+ bool copy_call_to_asset (void);
+ void fill_in_prep_code (void);
+ void fill_in_command (void);
+ add_policy_usage_call (tf_fuzz_info *test_state, long &asset_ser_no,
+ asset_search how_asset_found); // (constructor)
+ ~add_policy_usage_call (void);
+
+
+protected:
+ // Data members:
+ // Methods:
+
+private:
+ // Data members:
+ // Methods:
+};
+
+
+class set_policy_lifetime_call : public policy_call
+{
+public:
+ // Data members:
+ // Methods:
+ bool copy_call_to_asset (void);
+ void fill_in_prep_code (void);
+ void fill_in_command (void);
+ set_policy_lifetime_call (tf_fuzz_info *test_state, long &asset_ser_no,
+ asset_search how_asset_found); // (constructor)
+ ~set_policy_lifetime_call (void);
+
+
+protected:
+ // Data members:
+ // Methods:
+
+private:
+ // Data members:
+ // Methods:
+};
+
+
+class set_policy_algorithm_call : public policy_call
+{
+public:
+ // Data members:
+ // Methods:
+ bool copy_call_to_asset (void);
+ void fill_in_prep_code (void);
+ void fill_in_command (void);
+ set_policy_algorithm_call (tf_fuzz_info *test_state, long &asset_ser_no,
+ asset_search how_asset_found); // (constructor)
+ ~set_policy_algorithm_call (void);
+
+
+protected:
+ // Data members:
+ // Methods:
+
+private:
+ // Data members:
+ // Methods:
+};
+
+
+class set_policy_size_call : public policy_call
+{
+public:
+ // Data members:
+ // Methods:
+ bool copy_call_to_asset (void);
+ void fill_in_prep_code (void);
+ void fill_in_command (void);
+ set_policy_size_call (tf_fuzz_info *test_state, long &asset_ser_no,
+ asset_search how_asset_found); // (constructor)
+ ~set_policy_size_call (void);
+
+
+protected:
+ // Data members:
+ // Methods:
+
+private:
+ // Data members:
+ // Methods:
+};
+
+
+class set_policy_type_call : public policy_call
+{
+public:
+ // Data members:
+ // Methods:
+ bool copy_call_to_asset (void);
+ void fill_in_prep_code (void);
+ void fill_in_command (void);
+ set_policy_type_call (tf_fuzz_info *test_state, long &asset_ser_no,
+ asset_search how_asset_found); // (constructor)
+ ~set_policy_type_call (void);
+
+
+protected:
+ // Data members:
+ // Methods:
+
+private:
+ // Data members:
+ // Methods:
+};
+
+
+class get_policy_lifetime_call : public policy_call
+{
+public:
+ // Data members:
+ // Methods:
+ bool copy_call_to_asset (void);
+ void fill_in_prep_code (void);
+ void fill_in_command (void);
+ get_policy_lifetime_call (tf_fuzz_info *test_state, long &asset_ser_no,
+ asset_search how_asset_found); // (constructor)
+ ~get_policy_lifetime_call (void);
+
+
+protected:
+ // Data members:
+ // Methods:
+
+private:
+ // Data members:
+ // Methods:
+};
+
+
+class get_policy_size_call : public policy_call
+{
+public:
+ // Data members:
+ // Methods:
+ bool copy_call_to_asset (void);
+ void fill_in_prep_code (void);
+ void fill_in_command (void);
+ get_policy_size_call (tf_fuzz_info *test_state, long &asset_ser_no,
+ asset_search how_asset_found); // (constructor)
+ ~get_policy_size_call (void);
+
+
+protected:
+ // Data members:
+ // Methods:
+
+private:
+ // Data members:
+ // Methods:
+};
+
+
+class get_policy_type_call : public policy_call
+{
+public:
+ // Data members:
+ // Methods:
+ bool copy_call_to_asset (void);
+ void fill_in_prep_code (void);
+ void fill_in_command (void);
+ get_policy_type_call (tf_fuzz_info *test_state, long &asset_ser_no,
+ asset_search how_asset_found); // (constructor)
+ ~get_policy_type_call (void);
+
+
+protected:
+ // Data members:
+ // Methods:
+
+private:
+ // Data members:
+ // Methods:
+};
+
+
+class get_policy_algorithm_call : public policy_call
+{
+public:
+ // Data members:
+ // Methods:
+ bool copy_call_to_asset (void);
+ void fill_in_prep_code (void);
+ void fill_in_command (void);
+ get_policy_algorithm_call (tf_fuzz_info *test_state, long &asset_ser_no,
+ asset_search how_asset_found); // (constructor)
+ ~get_policy_algorithm_call (void);
+
+
+protected:
+ // Data members:
+ // Methods:
+
+private:
+ // Data members:
+ // Methods:
+};
+
+
+class get_policy_usage_call : public policy_call
+{
+public:
+ // Data members:
+ // Methods:
+ bool copy_call_to_asset (void);
+ void fill_in_prep_code (void);
+ void fill_in_command (void);
+ get_policy_usage_call (tf_fuzz_info *test_state, long &asset_ser_no,
+ asset_search how_asset_found); // (constructor)
+ ~get_policy_usage_call (void);
+
+
+protected:
+ // Data members:
+ // Methods:
+
+private:
+ // Data members:
+ // Methods:
+};
+
+
+/* This is not actually a PSA call; it just emits code to print out, to the log,
+ information about the usage info retrieved in a get_policy_usage_call above. */
+class print_policy_usage_call : public policy_call
+{
+public:
+ // Data members:
+ // Methods:
+ bool copy_call_to_asset (void);
+ void fill_in_prep_code (void);
+ void fill_in_command (void);
+ print_policy_usage_call (tf_fuzz_info *test_state, long &asset_ser_no,
+ asset_search how_asset_found); // (constructor)
+ ~print_policy_usage_call (void);
+
+
+protected:
+ // Data members:
+ // Methods:
+
+private:
+ // Data members:
+ // Methods:
+};
+
+
+class get_key_policy_call : public policy_call
+{
+public:
+ // Data members:
+ // Methods:
+ bool copy_call_to_asset (void);
+ void fill_in_prep_code (void);
+ void fill_in_command (void);
+ get_key_policy_call (tf_fuzz_info *test_state, long &asset_ser_no,
+ asset_search how_asset_found); // (constructor)
+ ~get_key_policy_call (void);
+
+
+protected:
+ // Data members:
+ // Methods:
+
+private:
+ // Data members:
+ // Methods:
+};
+
+
+/**********************************************************************************
+ End of derived classes of class policy_call.
+**********************************************************************************/
+
+
+/**********************************************************************************
+ Derived classes of class key_call follow:
+**********************************************************************************/
+
+
+class generate_key_call : public key_call
+{
+public:
+ // Data members:
+ // Methods:
+ bool copy_call_to_asset (void);
+ void fill_in_prep_code (void);
+ void fill_in_command (void);
+ generate_key_call (tf_fuzz_info *test_state, long &asset_ser_no,
+ asset_search how_asset_found); // (constructor)
+ ~generate_key_call (void);
+
+
+protected:
+ // Data members:
+ // Methods:
+
+private:
+ // Data members:
+ // Methods:
+};
+
+
+class create_key_call : public key_call
+{
+public:
+ // Data members:
+ // Methods:
+ bool copy_call_to_asset (void);
+ void fill_in_prep_code (void);
+ void fill_in_command (void);
+ create_key_call (tf_fuzz_info *test_state, long &asset_ser_no,
+ asset_search how_asset_found); // (constructor)
+ ~create_key_call (void);
+
+
+protected:
+ // Data members:
+ // Methods:
+
+private:
+ // Data members:
+ // Methods:
+};
+
+
+class copy_key_call : public key_call
+{
+public:
+ // Data members:
+ // Methods:
+ bool copy_call_to_asset (void);
+ void fill_in_prep_code (void);
+ void fill_in_command (void);
+ copy_key_call (tf_fuzz_info *test_state, long &asset_ser_no,
+ asset_search how_asset_found); // (constructor)
+ ~copy_key_call (void);
+
+
+protected:
+ // Data members:
+ // Methods:
+
+private:
+ // Data members:
+ // Methods:
+};
+
+
+class read_key_data_call : public key_call
+{
+public:
+ // Data members:
+ // Methods:
+ bool copy_call_to_asset (void);
+ void fill_in_prep_code (void);
+ void fill_in_command (void);
+ read_key_data_call (tf_fuzz_info *test_state, long &asset_ser_no,
+ asset_search how_asset_found); // (constructor)
+ ~read_key_data_call (void);
+
+
+protected:
+ // Data members:
+ // Methods:
+
+private:
+ // Data members:
+ // Methods:
+};
+
+
+class remove_key_call : public key_call
+{
+public:
+ // Data members:
+ // Methods:
+ bool copy_call_to_asset (void);
+ void fill_in_prep_code (void);
+ void fill_in_command (void);
+ remove_key_call (tf_fuzz_info *test_state, long &asset_ser_no,
+ asset_search how_asset_found); // (constructor)
+ ~remove_key_call (void);
+
+
+protected:
+ // Data members:
+ // Methods:
+
+private:
+ // Data members:
+ // Methods:
+};
+
+
+/**********************************************************************************
+ End of derived classes of class key_call.
+**********************************************************************************/
+
+#endif // CRYPTO_CALL_HPP
diff --git a/tf_fuzz/calls/crypto_call.o b/tf_fuzz/calls/crypto_call.o
new file mode 100644
index 0000000..d2840ff
--- /dev/null
+++ b/tf_fuzz/calls/crypto_call.o
Binary files differ
diff --git a/tf_fuzz/calls/psa_call.cpp b/tf_fuzz/calls/psa_call.cpp
new file mode 100644
index 0000000..46af409
--- /dev/null
+++ b/tf_fuzz/calls/psa_call.cpp
@@ -0,0 +1,350 @@
+/*
+ * 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->asset_info.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;
+ barrier = target_barrier = ""; // not (yet) any barrier for re-ordering calls
+ call_description = "";
+}
+
+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 (!exp_data.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)
+{
+ string formalized; // "proper" result string
+
+ if (!exp_data.pf_nothing) {
+ if (exp_data.pf_pass) {
+ find_replace_all ("$expect",
+ test_state->bplate->bplate_string[sst_pass_string],
+ check_code);
+ } else if (exp_data.pf_fail) {
+ // Check for not-success:
+ find_replace_1st ("!=", "==",
+ check_code);
+ find_replace_all ("$expect",
+ test_state->bplate->bplate_string[sst_pass_string],
+ check_code);
+ find_replace_1st ("expected ", "expected not ",
+ check_code);
+ } else {
+ if (exp_data.pf_specified) {
+ formalized = formalize (exp_data.pf_result_string, "PSA_ERROR_");
+ find_replace_all ("$expect", formalized, check_code);
+ } else {
+ // Figure out what the message should read:
+ switch (asset_info.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); // like "fail", just make sure...
+ find_replace_all ("$expect",
+ test_state->bplate->
+ bplate_string[sst_pass_string],
+ check_code); // ... it's *not* PSA_SUCCESS
+ break;
+ }
+ }
+ }
+ }
+}
+
+vector<psa_asset*>::iterator sst_call::resolve_asset (bool create_asset_bool,
+ psa_asset_usage where) {
+ vector<psa_asset*>::iterator found_asset;
+ vector<psa_asset*> *asset_vector;
+ int asset_pick;
+
+ if (random_asset != psa_asset_usage::all) {
+ // != psa_asset_usage::all means to choose some known asset at random:
+ if (random_asset == psa_asset_usage::active) {
+ asset_vector = &(test_state->active_sst_asset);
+ asset_info.how_asset_found = asset_search::found_active;
+ } else if (random_asset == psa_asset_usage::deleted) {
+ asset_vector = &(test_state->deleted_sst_asset);
+ asset_info.how_asset_found = asset_search::found_deleted;
+ } else {
+ // "invalid" assets are not currently used.
+ cerr << "\nError: Tool-internal: Please report error 1101 to " << endl
+ << "TF-Fuzz developers."
+ << endl;
+ exit(1101);
+ }
+ if (asset_vector->size() > 0) {
+ /* Pick an active or deleted asset at random: */
+ asset_pick = rand() % asset_vector->size();
+ found_asset = asset_vector->begin() + asset_pick;
+ /* Copy asset information into template tracker: */
+ asset_info.id_n = (*found_asset)->asset_info.id_n;
+ asset_info.asset_ser_no
+ = (*found_asset)->asset_info.asset_ser_no;
+ } else {
+ if (random_asset == psa_asset_usage::active) {
+ cerr << "\nError: An sst call asks for a "
+ << "randomly chosen active asset, when none " << endl
+ << "is currently defined." << endl;
+ exit(1008);
+ } else if (random_asset == psa_asset_usage::deleted) {
+ cerr << "\nError: An sst call asks for a "
+ << "randomly chosen deleted asset, when none " << endl
+ << "is currently defined." << endl;
+ exit(1009);
+ } // "invalid" assets are not currently used.
+ }
+ } else {
+ // Find the asset by name:
+ asset_info.how_asset_found = test_state->find_or_create_sst_asset (
+ psa_asset_search::name, where,
+ asset_info.get_name(), 0, asset_info.asset_ser_no,
+ create_asset_bool, found_asset );
+ if ( asset_info.how_asset_found == asset_search::unsuccessful
+ || asset_info.how_asset_found == asset_search::something_wrong ) {
+ cerr << "\nError: Tool-internal: Please report error 108 to " << endl
+ << "TF-Fuzz developers."
+ << endl;
+ exit(108);
+ }
+ }
+ return found_asset;
+}
+
+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)
+{
+ asset_info.the_asset = nullptr;
+ 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)
+{
+ string formalized; // "proper" result string
+
+ if (!exp_data.pf_nothing) {
+ if (exp_data.pf_pass) {
+ find_replace_all ("$expect",
+ test_state->bplate->bplate_string[sst_pass_string],
+ check_code);
+ } else if (exp_data.pf_fail) {
+ // Check for not-success:
+ find_replace_1st ("!=", "==",
+ check_code);
+ find_replace_all ("$expect",
+ test_state->bplate->bplate_string[sst_pass_string],
+ check_code);
+ find_replace_1st ("expected ", "expected not ",
+ check_code);
+ } else {
+ if (exp_data.pf_specified) {
+ formalized = formalize (exp_data.pf_result_string, "PSA_ERROR_");
+ find_replace_all ("$expect", formalized, check_code);
+ } else {
+ // Figure out what the message should read:
+ switch (asset_info.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::not_found:
+ case asset_search::found_deleted:
+ find_replace_all ("$expect", "PSA_ERROR_INVALID_HANDLE",
+ check_code); // TODO: take from boilerplate
+ break;
+ default:
+ find_replace_1st ("!=", "==",
+ check_code); // like "fail", just make sure...
+ find_replace_all ("$expect",
+ test_state->bplate->
+ bplate_string[sst_pass_string],
+ check_code); // ... it's *not* PSA_SUCCESS
+ break;
+ }
+ }
+ }
+ }
+}
+
+
+bool crypto_call::copy_asset_to_call (void)
+{
+ if (asset_info.the_asset == nullptr) {
+ return false;
+ } else {
+ // Get updated asset info from the asset:
+ asset_info.asset_ser_no = asset_info.the_asset->asset_info.asset_ser_no;
+ asset_info.id_n = asset_info.the_asset->asset_info.id_n;
+ exp_data.n_exp_vars = asset_info.the_asset->exp_data.n_exp_vars;
+ exp_data.data = asset_info.the_asset->exp_data.data;
+ return true;
+ }
+}
+
+
+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
+}
+
+// resolve_asset() doesn't do anything for security_calls, since there's no asset involved.
+vector<psa_asset*>::iterator security_call::resolve_asset (bool create_asset_bool,
+ psa_asset_usage where)
+{
+ return test_state->active_sst_asset.end(); // (anything)
+}
+
+/* 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/tf_fuzz/calls/psa_call.hpp b/tf_fuzz/calls/psa_call.hpp
new file mode 100644
index 0000000..ed66245
--- /dev/null
+++ b/tf_fuzz/calls/psa_call.hpp
@@ -0,0 +1,158 @@
+/*
+ * 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: */
+ string call_description; // description of the call, just for tracing
+ expect_info exp_data; // everything about expected results
+ set_data_info set_data; // everything about setting PSA-asset-data values
+ asset_name_id_info asset_info; // everything about the asset(s) for this line
+ key_policy_info policy; // (specific to crypto, but have to put this here)
+ string asset_2_name; // if there's a 2nd asset, then this is its name
+ string asset_3_name; // if there's a 3rd asset, then this is its name
+ 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. */
+ bool assign_data_var_specified; // asset data to/from named variable
+ string assign_data_var; // name of variable to dump (assign) data into
+ // 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 call_ser_no; // unique serial# for this psa_call (see note in tf_fuzz.hpp)
+ tf_fuzz_info *test_state; // the big blob with pointers to everything going on
+ string barrier;
+ /* "barrier" is used for template-line operations that resolve a series of
+ PSA calls. In particular, with respect to the fact that TF-Fuzz strives
+ to randomize these multiple calls where possible, meaning interspersing
+ them among other, earlier commands. However, for example, calls to set
+ the aspects of a policy can't be pushed too far back, such as in among
+ calls setting that same policy for a previous operation! "barrier" is
+ either "", in which case this call does not care whether you place calls
+ before it, or it contains the name of an asset that, calls related to
+ which must be placed *after* this call. */
+ string target_barrier;
+ /* asset to tell the psa_call objects to set and search barrier to when
+ re-ordering PSA calls. For key policies, this is not necessarily the
+ nominal asset of that call. For a policy call, it is that policy asset,
+ so that later re-settings of the same policy don't pollute the current
+ setting of that policy. However, for key sets and reads, it is not the
+ key asset, but its policy. */
+ // Methods:
+ virtual vector<psa_asset*>::iterator resolve_asset (bool create_asset_bool,
+ psa_asset_usage where) = 0;
+ virtual bool copy_call_to_asset (void) = 0;
+ virtual bool copy_asset_to_call (void) = 0;
+ 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:
+ vector<psa_asset*>::iterator resolve_asset (bool create_asset_bool,
+ psa_asset_usage where);
+ 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)
+ // Methods:
+ bool copy_asset_to_call (void);
+ 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:
+ vector<psa_asset*>::iterator resolve_asset (bool create_asset_bool,
+ psa_asset_usage where);
+ 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/tf_fuzz/calls/psa_call.o b/tf_fuzz/calls/psa_call.o
new file mode 100644
index 0000000..7caabe5
--- /dev/null
+++ b/tf_fuzz/calls/psa_call.o
Binary files differ
diff --git a/tf_fuzz/calls/security_call.cpp b/tf_fuzz/calls/security_call.cpp
new file mode 100644
index 0000000..a99496a
--- /dev/null
+++ b/tf_fuzz/calls/security_call.cpp
@@ -0,0 +1,93 @@
+/*
+ * 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)
+{
+ call_description = "hash call";
+}
+hash_call::~hash_call (void)
+{
+ // Nothing further to delete.
+ return; // just to have something to pin a breakpoint onto
+}
+
+bool hash_call::copy_call_to_asset (void)
+{
+ // The assets are not directly involved in this call.
+ return true;
+}
+
+bool hash_call::copy_asset_to_call (void)
+{
+ // The assets are not directly involved in this call.
+ return true;
+}
+
+/* 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_info.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_info.asset_name_vector.begin();
+ outer < asset_info.asset_name_vector.end();
+ ++outer) {
+ for (auto inner = outer+1;
+ inner < asset_info.asset_name_vector.end();
+ ++inner) {
+ call_code.append (" if ( " + *outer + "_act_hash == " + *inner
+ + "_act_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");
+ // TODO: Pull this from boilerplate!!
+ }
+ }
+ } else {
+ call_code.assign (" /* Cannot compare hashes; only one asset specified. */\n");
+
+ }
+}
+
+/**********************************************************************************
+ End of methods of class hash_call.
+**********************************************************************************/
diff --git a/tf_fuzz/calls/security_call.hpp b/tf_fuzz/calls/security_call.hpp
new file mode 100644
index 0000000..e55a278
--- /dev/null
+++ b/tf_fuzz/calls/security_call.hpp
@@ -0,0 +1,48 @@
+/*
+ * 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:
+ bool copy_call_to_asset (void);
+ bool copy_asset_to_call (void);
+ 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/tf_fuzz/calls/security_call.o b/tf_fuzz/calls/security_call.o
new file mode 100644
index 0000000..5cfd78c
--- /dev/null
+++ b/tf_fuzz/calls/security_call.o
Binary files differ
diff --git a/tf_fuzz/calls/sst_call.cpp b/tf_fuzz/calls/sst_call.cpp
new file mode 100644
index 0000000..9aa7762
--- /dev/null
+++ b/tf_fuzz/calls/sst_call.cpp
@@ -0,0 +1,492 @@
+/*
+ * 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"
+#include "variables.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]);
+ call_description = "SST-set call";
+}
+sst_set_call::~sst_set_call (void)
+{
+ return; // just to have something to pin a breakpoint onto
+}
+
+bool sst_set_call::copy_call_to_asset (void)
+{
+ vector<psa_asset*>::iterator found_asset;
+
+ found_asset = resolve_asset (yes_create_asset, psa_asset_usage::all);
+ // Copy over everything relevant:
+ if (asset_info.how_asset_found != asset_search::not_found) {
+ asset_info.the_asset = reinterpret_cast<sst_asset*>(*found_asset);
+ /* Note: The vector is base-class, but the assets in this list
+ themselves *really are* sst_asset-type objects. */
+ int i = asset_info.the_asset->set_data.n_set_vars; // save this
+ asset_info.the_asset->set_data = set_data; // TO DO: does this make sense?!
+ asset_info.the_asset->set_data.n_set_vars = set_data.n_set_vars = ++i;
+ asset_info.the_asset->set_data.flags_string.assign (set_data.flags_string);
+ if (asset_info.how_asset_found == asset_search::created_new) {
+ asset_info.the_asset->asset_info.name_specified = asset_info.name_specified;
+ asset_info.the_asset->asset_info.set_name (asset_info.get_name());
+ asset_info.the_asset->asset_info.asset_ser_no = asset_info.asset_ser_no;
+ asset_info.the_asset->asset_info.id_n = asset_info.id_n;
+ }
+ }
+ return true;
+}
+
+bool sst_set_call::copy_asset_to_call (void)
+{
+ // Get updated asset info from the asset:
+ asset_info.asset_ser_no = asset_info.the_asset->asset_info.asset_ser_no;
+ asset_info.id_n = asset_info.the_asset->asset_info.id_n;
+ exp_data.n_exp_vars = asset_info.the_asset->exp_data.n_exp_vars;
+ exp_data.data = asset_info.the_asset->exp_data.data;
+ return true;
+}
+
+void sst_set_call::fill_in_prep_code (void)
+{
+ string var_name, length_var_name, var_name_suffix, length_var_name_suffix,
+ temp_string;
+ vector<variable_info>::iterator assign_variable;
+
+ if (assign_data_var_specified) {
+ var_name.assign (assign_data_var + "_data");
+ length_var_name.assign (assign_data_var + "_length");
+ /* If actual-data variable doesn't already exist, create variable tracker,
+ and write declaration for it: */
+ assign_variable = test_state->find_var (assign_data_var);
+ if (assign_variable == test_state->variable.end()) {
+ // No such variable exists, so:
+ test_state->make_var (assign_data_var);
+ assign_variable = test_state->find_var (assign_data_var);
+ prep_code.append (test_state->bplate->bplate_string[declare_big_string]);
+ find_replace_1st ("$var", var_name, prep_code);
+ temp_string = (char *) assign_variable->value;
+ find_replace_1st ("$init", temp_string, prep_code);
+ // Actual-data length:
+ prep_code.append (test_state->bplate->bplate_string[declare_size_t]);
+ find_replace_1st ("$var", length_var_name, prep_code);
+ find_replace_1st ("$init", to_string(temp_string.length()), prep_code);
+ // Offset (always 0 for now):
+ find_replace_1st ("$offset", "0", prep_code);
+ }
+ } else {
+ // Single string of two lines declaring string data and its length:
+ var_name_suffix = "_set_data";
+ length_var_name_suffix = "_set_length";
+ if (set_data.n_set_vars > 0) {
+ var_name_suffix += "_" + to_string(set_data.n_set_vars);
+ length_var_name_suffix += "_" + to_string(set_data.n_set_vars);
+ // We'll increment set_data.n_set_vars after we fill in the call itself.
+ }
+ var_name.assign (asset_info.get_name() + var_name_suffix);
+ length_var_name.assign (asset_info.get_name() + length_var_name_suffix);
+ 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);
+ temp_string.assign (test_state->bplate->bplate_string[declare_int]);
+ find_replace_1st ("static int", "static uint32_t", temp_string);
+ prep_code.append (temp_string);
+ find_replace_1st ("$var", length_var_name, prep_code);
+ find_replace_1st ("$init", to_string(set_data.get().length()), prep_code);
+ }
+}
+
+void sst_set_call::fill_in_command (void)
+{
+ string var_name, length_var_name, var_name_suffix, length_var_name_suffix,
+ temp_string;
+
+ // Fill in preceding comment:
+ if (asset_info.how_asset_found == asset_search::created_new) {
+ find_replace_1st ("$op", "Creating", call_code);
+ } else {
+ find_replace_1st ("$op", "Resetting", call_code);
+ }
+ if (asset_info.name_specified) {
+ find_replace_1st ("$description", "\"" + asset_info.get_name() + ",\"",
+ call_code);
+ } else {
+ find_replace_1st ("$description",
+ "UID = " + to_string((long) asset_info.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:
+ if (assign_data_var_specified) {
+ var_name.assign (assign_data_var + "_data");
+ length_var_name.assign (assign_data_var + "_length");
+ } else {
+ var_name_suffix = "_set_data";
+ if (set_data.n_set_vars > 0) {
+ var_name_suffix += "_" + to_string(set_data.n_set_vars);
+ }
+ var_name.assign (asset_info.get_name() + var_name_suffix);
+ length_var_name_suffix = "_set_length";
+ if (set_data.n_set_vars > 0) {
+ length_var_name_suffix += "_" + to_string(set_data.n_set_vars);
+ }
+ length_var_name.assign (asset_info.get_name() + length_var_name_suffix);
+ }
+ find_replace_1st ("$data", var_name, call_code);
+ find_replace_1st ("$flags", set_data.flags_string, call_code);
+ string id_string = to_string((long) asset_info.id_n);
+ find_replace_1st ("$uid", id_string, call_code);
+ find_replace_1st ("$length", length_var_name, call_code);
+ // Figure out what expected results:
+ if ( set_data.flags_string == "PSA_STORAGE_FLAG_WRITE_ONCE"
+ && set_data.n_set_vars > 0) {
+ exp_data.pf_specified = true;
+ exp_data.pf_result_string = "PSA_ERROR_NOT_PERMITTED";
+ }
+ 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()
+ call_description = "SST-get call";
+}
+sst_get_call::~sst_get_call (void)
+{
+ return; // just to have something to pin a breakpoint onto
+}
+
+bool sst_get_call::copy_call_to_asset (void)
+{
+ vector<psa_asset*>::iterator found_asset;
+
+ found_asset = resolve_asset (dont_create_asset, psa_asset_usage::active);
+ if (asset_info.how_asset_found != asset_search::not_found) {
+ // will be found for set calls, but not necessarily others
+ asset_info.the_asset = reinterpret_cast<sst_asset*>(*found_asset);
+ // Note: Vector is of base-class type, but the assets *are* sst_asset.
+ /* Locating the asset is all we need to do here; copy_asset_to_call() will
+ do the rest. */
+ }
+ return true;
+ // TODO: Shouldn't data be copied over?
+}
+
+bool sst_get_call::copy_asset_to_call (void)
+{
+ if (asset_info.the_asset != nullptr) {
+ // will be found for set calls, but not necessarily others
+ set_data.string_specified = asset_info.the_asset->set_data.string_specified;
+ set_data.file_specified = asset_info.the_asset->set_data.file_specified;
+ set_data.set (asset_info.the_asset->set_data.get());
+ set_data.flags_string = asset_info.the_asset->set_data.flags_string;
+ asset_info.id_n = asset_info.the_asset->asset_info.id_n;
+ asset_info.asset_ser_no = asset_info.the_asset->asset_info.asset_ser_no;
+ asset_info.name_specified = asset_info.the_asset->asset_info.name_specified;
+ asset_info.the_asset->exp_data.n_exp_vars++;
+ exp_data.n_exp_vars = asset_info.the_asset->exp_data.n_exp_vars;
+ }
+ return true;
+}
+
+void sst_get_call::fill_in_prep_code (void)
+{
+ string var_base, var_name, length_var_name, temp_string, var_name_suffix,
+ expected;
+ vector<variable_info>::iterator act_variable, exp_variable;
+
+ if (!(print_data || hash_data)) {
+ // Checking asset data verbatim against expected, so:
+ if (exp_data.data_var_specified) {
+ // Template specified a variable name to "check" against; use that:
+ var_base.assign (exp_data.data_var);
+ exp_variable = test_state->find_var (var_base);
+ if (exp_variable == test_state->variable.end()) {
+ test_state->make_var (var_base);
+ exp_variable = test_state->find_var (var_base);
+ var_name = var_base + "_data";
+ prep_code.append (test_state->bplate->bplate_string[declare_string]);
+ find_replace_1st ("$var", var_name, prep_code);
+ temp_string = (char *) exp_variable->value;
+ find_replace_1st ("$init", temp_string, prep_code);
+ // Expected-data length:
+ temp_string.assign (test_state->bplate->bplate_string[declare_int]);
+ find_replace_1st ("static int", "static size_t", temp_string);
+ }
+ } else {
+ if (exp_data.data_specified) {
+ // Checking against literal expected data:
+ expected.assign (exp_data.data);
+ } else {
+ // Check against what we believe the asset to contain:
+ expected.assign (set_data.get());
+ }
+ var_name_suffix = "_exp_data";
+ if (exp_data.n_exp_vars > 0) {
+ var_name_suffix =
+ var_name_suffix + "_" + to_string(exp_data.n_exp_vars);
+ }
+ var_name.assign (asset_info.get_name() + var_name_suffix);
+ prep_code.assign(test_state->bplate->bplate_string[declare_string]);
+ find_replace_1st("$var", var_name, prep_code);
+ find_replace_1st("$init", expected, prep_code);
+ }
+ }
+ // Actual data:
+ if (assign_data_var_specified) {
+ var_base.assign (assign_data_var);
+ } else {
+ var_base.assign (asset_info.get_name() + "_act");
+ }
+ var_name.assign (var_base + "_data");
+ length_var_name.assign (var_base + "_length");
+ /* If actual-data variable doesn't already exist, create variable tracker,
+ and write declaration for it: */
+ act_variable = test_state->find_var (var_base);
+ if (act_variable == test_state->variable.end()) {
+ test_state->make_var (var_base);
+ act_variable = test_state->find_var (var_base);
+ prep_code.append (test_state->bplate->bplate_string[declare_big_string]);
+ find_replace_1st ("$var", var_name, prep_code);
+ temp_string = (char *) act_variable->value;
+ find_replace_1st ("$init", temp_string, prep_code);
+ // Actual-data 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", length_var_name, prep_code);
+ find_replace_1st ("$init", to_string(temp_string.length()), 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 && !act_variable->hash_declared) {
+ var_name = var_base + "_hash";
+ prep_code.append (test_state->bplate->bplate_string[declare_generic]);
+ // 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...
+ act_variable->hash_declared = true;
+ }
+}
+
+void sst_get_call::fill_in_command (void)
+{
+ string exp_var_name, act_var_name, act_data_length, hash_var_name,
+ id_string, var_name_suffix;
+
+/* TODO: Flesh-out/fix this (it was a good try/start, but not quite right):
+ // Fill in preceding comment:
+ if (asset_info.how_asset_found == asset_search::created_new) {
+ find_replace_1st ("$op", "Creating", call_code);
+ } else {
+ find_replace_1st ("$op", "Resetting", call_code);
+ }
+ if (asset_info.name_specified) {
+ find_replace_1st ("$description", "\"" + asset_info.get_name() + ",\"",
+ call_code);
+ } else {
+ find_replace_1st ("$description",
+ "UID = " + to_string((long) asset_info.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 (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 too:
+ 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 (exp_data.data_var_specified) {
+ // Check against data in variable:
+ exp_var_name.assign (exp_data.data_var + "_data");
+ } else {
+ var_name_suffix = "_exp_data";
+ if (exp_data.n_exp_vars > 0) {
+ var_name_suffix =
+ var_name_suffix + "_" + to_string(exp_data.n_exp_vars);
+ }
+ exp_var_name.assign (asset_info.get_name() + var_name_suffix);
+ }
+ if (assign_data_var_specified) {
+ act_var_name.assign (assign_data_var + "_data");
+ act_data_length.assign (assign_data_var + "_length");
+ } else {
+ act_var_name.assign (asset_info.get_name() + "_act_data");
+ act_data_length.assign (asset_info.get_name() + "_act_length");
+ }
+
+ id_string = to_string((long) asset_info.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", to_string(set_data.data_offset), 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", act_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_info.get_name() + "_act_hash");
+ // this is 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]);
+ call_description = "SST-remove call";
+}
+sst_remove_call::~sst_remove_call (void)
+{
+ return; // just to have something to pin a breakpoint onto
+}
+
+bool sst_remove_call::copy_call_to_asset (void)
+{
+ vector<psa_asset*>::iterator found_asset;
+
+ found_asset = resolve_asset (dont_create_asset, psa_asset_usage::all);
+ if (asset_info.how_asset_found != asset_search::not_found) {
+ asset_info.the_asset = reinterpret_cast<sst_asset*>(*found_asset);
+ // Note: Vector is of base-class type, but the assets *are* sst_asset.
+ if (asset_info.how_asset_found == asset_search::found_active) {
+ // Delete asset; move it from active vector to deleted vector:
+ test_state->deleted_sst_asset.push_back (asset_info.the_asset);
+ test_state->active_sst_asset.erase (found_asset);
+ } /* if not active, we'll deem the call expected to fail. */
+ }
+ return true;
+}
+
+bool sst_remove_call::copy_asset_to_call (void)
+{
+ if (asset_info.the_asset != nullptr) {
+ set_data.string_specified = asset_info.the_asset->set_data.string_specified;
+ set_data.file_specified = asset_info.the_asset->set_data.file_specified;
+ set_data.flags_string = asset_info.the_asset->set_data.flags_string;
+ asset_info.id_n = asset_info.the_asset->asset_info.id_n;
+ asset_info.name_specified = asset_info.the_asset->asset_info.name_specified;
+ }
+ return true;
+}
+
+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_info.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/tf_fuzz/calls/sst_call.hpp b/tf_fuzz/calls/sst_call.hpp
new file mode 100644
index 0000000..537b21f
--- /dev/null
+++ b/tf_fuzz/calls/sst_call.hpp
@@ -0,0 +1,96 @@
+/*
+ * 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:
+ bool copy_call_to_asset (void);
+ bool copy_asset_to_call (void);
+ 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:
+ bool copy_call_to_asset (void);
+ bool copy_asset_to_call (void);
+ 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:
+ bool copy_call_to_asset (void);
+ bool copy_asset_to_call (void);
+ 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/tf_fuzz/calls/sst_call.o b/tf_fuzz/calls/sst_call.o
new file mode 100644
index 0000000..8b92b0d
--- /dev/null
+++ b/tf_fuzz/calls/sst_call.o
Binary files differ
diff --git a/tf_fuzz/class_forwards.hpp b/tf_fuzz/class_forwards.hpp
new file mode 100644
index 0000000..6099fbe
--- /dev/null
+++ b/tf_fuzz/class_forwards.hpp
@@ -0,0 +1,114 @@
+/*
+ * 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;
+
+// find_or_create_asset.hpp:
+enum class asset_search;
+enum class psa_asset_usage;
+enum class psa_asset_search;
+enum class psa_asset_type;
+
+// data_blocks.hpp:
+class expect_info;
+class set_data_info;
+class asset_name_id_info;
+
+// variables.hpp:
+class variable_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;
+class sst_call;
+class crypto_call;
+
+// sst_call.hpp:
+class sst_set_call;
+class sst_get_call;
+class sst_remove_call;
+
+// crypto_call.hpp:
+class policy_call;
+class key_call;
+class init_policy_call;
+class reset_policy_call;
+class set_policy_usage_call;
+class add_policy_usage_call;
+class set_policy_lifetime_call;
+class set_policy_algorithm_call;
+class set_policy_size_call;
+class set_policy_type_call;
+class get_policy_lifetime_call;
+class get_policy_size_call;
+class get_policy_type_call;
+class get_policy_algorithm_call;
+class get_policy_usage_call;
+class print_policy_usage_call;
+class get_key_policy_call;
+class generate_key_call;
+class create_key_call;
+class copy_key_call;
+class read_key_data_call;
+class remove_key_call;
+
+
+// ************************ INSERT THE NEW STUFF HERE!!
+
+
+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/tf_fuzz/demo/1 b/tf_fuzz/demo/1
new file mode 100644
index 0000000..7b84f11
--- /dev/null
+++ b/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/tf_fuzz/demo/10 b/tf_fuzz/demo/10
new file mode 100644
index 0000000..3e70099
--- /dev/null
+++ b/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/tf_fuzz/demo/11 b/tf_fuzz/demo/11
new file mode 100644
index 0000000..5fdd0fc
--- /dev/null
+++ b/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/tf_fuzz/demo/12 b/tf_fuzz/demo/12
new file mode 100644
index 0000000..c7825c5
--- /dev/null
+++ b/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/tf_fuzz/demo/12.5 b/tf_fuzz/demo/12.5
new file mode 100644
index 0000000..2e7004b
--- /dev/null
+++ b/tf_fuzz/demo/12.5
@@ -0,0 +1,2 @@
+purpose to more-specifically override TF-Fuzz's expected result;
+read sst name napoleon check "this won't work" expect generic_error;
diff --git a/tf_fuzz/demo/13 b/tf_fuzz/demo/13
new file mode 100644
index 0000000..7edb72e
--- /dev/null
+++ b/tf_fuzz/demo/13
@@ -0,0 +1,4 @@
+purpose to illustrate deleting assets;
+set sst name george data *;
+remove sst name george;
+rm sst name george;
diff --git a/tf_fuzz/demo/14 b/tf_fuzz/demo/14
new file mode 100644
index 0000000..5b9485c
--- /dev/null
+++ b/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/tf_fuzz/demo/15 b/tf_fuzz/demo/15
new file mode 100644
index 0000000..613439e
--- /dev/null
+++ b/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/tf_fuzz/demo/16 b/tf_fuzz/demo/16
new file mode 100644
index 0000000..528a0ec
--- /dev/null
+++ b/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
+rm sst *active; // remove *some other* active asset
+remove sst *act; // remove *yet another* active asset
+rm sst *del; // attempt to remove some asset that's already been removed
diff --git a/tf_fuzz/demo/17 b/tf_fuzz/demo/17
new file mode 100644
index 0000000..bdaeece
--- /dev/null
+++ b/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/tf_fuzz/demo/18 b/tf_fuzz/demo/18
new file mode 100644
index 0000000..f71335e
--- /dev/null
+++ b/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/tf_fuzz/demo/19 b/tf_fuzz/demo/19
new file mode 100644
index 0000000..173c45d
--- /dev/null
+++ b/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/tf_fuzz/demo/2 b/tf_fuzz/demo/2
new file mode 100644
index 0000000..9af02c6
--- /dev/null
+++ b/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/tf_fuzz/demo/20 b/tf_fuzz/demo/20
new file mode 100644
index 0000000..6fda99a
--- /dev/null
+++ b/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/tf_fuzz/demo/21 b/tf_fuzz/demo/21
new file mode 100644
index 0000000..8a609e2
--- /dev/null
+++ b/tf_fuzz/demo/21
@@ -0,0 +1,2 @@
+purpose to define a policy mostly-default (random) policy;
+set policy name nothingMuch attr export volatile;
diff --git a/tf_fuzz/demo/22 b/tf_fuzz/demo/22
new file mode 100644
index 0000000..fba0d53
--- /dev/null
+++ b/tf_fuzz/demo/22
@@ -0,0 +1,2 @@
+purpose to create a policy with random name, with type and algorithm using abbreviated keywords;
+set policy name * type rsa_public_key alg rsa_pss_base;
diff --git a/tf_fuzz/demo/23 b/tf_fuzz/demo/23
new file mode 100644
index 0000000..deb35b2
--- /dev/null
+++ b/tf_fuzz/demo/23
@@ -0,0 +1,2 @@
+purpose to create multiple policies with attributes including key size (523);
+set policy name aPolicy anotherPolicy yetAnother alg sha_256 attr 523 noexport;
diff --git a/tf_fuzz/demo/24 b/tf_fuzz/demo/24
new file mode 100644
index 0000000..dddc8f3
--- /dev/null
+++ b/tf_fuzz/demo/24
@@ -0,0 +1,3 @@
+purpose to create a default (random) policy and then print it to the log;
+set policy name randomPolicy;
+read policy name randomPolicy print;
diff --git a/tf_fuzz/demo/25 b/tf_fuzz/demo/25
new file mode 100644
index 0000000..912019c
--- /dev/null
+++ b/tf_fuzz/demo/25
@@ -0,0 +1,3 @@
+purpose to create a default (random) policy and create a key using it (no key material specified);
+set policy name randomPolicy;
+set key name akey policy randomPolicy;
diff --git a/tf_fuzz/demo/26 b/tf_fuzz/demo/26
new file mode 100644
index 0000000..9093bd1
--- /dev/null
+++ b/tf_fuzz/demo/26
@@ -0,0 +1,4 @@
+purpose to create a default (random) policy and create a key using it (random key data specified), then copy that key with another random policy;
+set policy name randomPolicy anotherPolicy;
+set key name aKey policy randomPolicy data *;
+set key name aNewKey from aKey policy anotherPolicy;
diff --git a/tf_fuzz/demo/27 b/tf_fuzz/demo/27
new file mode 100644
index 0000000..76a62c8
--- /dev/null
+++ b/tf_fuzz/demo/27
@@ -0,0 +1,4 @@
+purpose to do the same sort of things as #26, but change around operands;
+set policy name randomPolicy anotherPolicy;
+set key name aKey data * policy randomPolicy;
+set key name aNewKey from *active policy anotherPolicy;
diff --git a/tf_fuzz/demo/28 b/tf_fuzz/demo/28
new file mode 100644
index 0000000..e9fd0d8
--- /dev/null
+++ b/tf_fuzz/demo/28
@@ -0,0 +1,4 @@
+purpose to create a key, then read the key data ("material") into a variable;
+set policy name somePolicy alg sha3_224 attr noexport volatile;
+set key name aKey data * policy somePolicy;
+read key name aKey var keyDataVar;
diff --git a/tf_fuzz/demo/29 b/tf_fuzz/demo/29
new file mode 100644
index 0000000..072b30d
--- /dev/null
+++ b/tf_fuzz/demo/29
@@ -0,0 +1,4 @@
+purpose to create a key, then read the key data ("material") into a variable;
+set policy name somePolicy attr copy decrypt persistent alg xts;
+set key name aKey data * policy somePolicy;
+read key name aKey check keyDataVar expect fail;
diff --git a/tf_fuzz/demo/3 b/tf_fuzz/demo/3
new file mode 100644
index 0000000..8f41603
--- /dev/null
+++ b/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/tf_fuzz/demo/30 b/tf_fuzz/demo/30
new file mode 100644
index 0000000..47ebe4c
--- /dev/null
+++ b/tf_fuzz/demo/30
@@ -0,0 +1,4 @@
+purpose to create a key, then read the key data ("material") into a variable;
+set policy name somePolicy alg rsa_pkcs1v15_sign_base attr derive noverify;
+set key name aKey data * policy somePolicy;
+read key name aKey check "12345678" expect fail;
diff --git a/tf_fuzz/demo/31 b/tf_fuzz/demo/31
new file mode 100644
index 0000000..18039a0
--- /dev/null
+++ b/tf_fuzz/demo/31
@@ -0,0 +1,4 @@
+purpose to create a key, then read the key data ("material") into a variable;
+set policy name somePolicy attr sign verify copy alg arc4;
+set key name aKey data * policy somePolicy;
+read key name aKey print;
diff --git a/tf_fuzz/demo/32 b/tf_fuzz/demo/32
new file mode 100644
index 0000000..533fcf5
--- /dev/null
+++ b/tf_fuzz/demo/32
@@ -0,0 +1,4 @@
+purpose to create then remove a key;
+set policy name somePolicy attr sign verify copy alg arc4;
+set key name aKey data * policy somePolicy;
+remove key name aKey;
diff --git a/tf_fuzz/demo/33 b/tf_fuzz/demo/33
new file mode 100644
index 0000000..5cfa287
--- /dev/null
+++ b/tf_fuzz/demo/33
@@ -0,0 +1,6 @@
+purpose to set SST creation flags;
+set sst name hasCF data "this asset has write-once" flag write_once;
+set sst name hasCF2 data "this asset has also write-once" flag wo;
+set sst name alsoHasCF data "this asset has no flags" flag none expect pass;
+set sst name alsoHasCF2 data "this asset has NO_CONFIDENTIALITY" flag ncf;
+set sst name yetAnother data "this asset has NO_REPLAY_PROTECTION" flag nrp;
diff --git a/tf_fuzz/demo/34 b/tf_fuzz/demo/34
new file mode 100644
index 0000000..9fa46e9
--- /dev/null
+++ b/tf_fuzz/demo/34
@@ -0,0 +1,3 @@
+purpose to set an offset on psa_ps_get();
+set sst name whoNose data *;
+read sst name whoNose print offset 10;
diff --git a/tf_fuzz/demo/35 b/tf_fuzz/demo/35
new file mode 100644
index 0000000..60fc978
--- /dev/null
+++ b/tf_fuzz/demo/35
@@ -0,0 +1,4 @@
+purpose to verify we can't write multiple times to a write-once SST asset;
+set sst name writeOnce data * flag wo;
+set sst name writeOnce data *;
+set sst name writeOnce data *;
diff --git a/tf_fuzz/demo/4 b/tf_fuzz/demo/4
new file mode 100644
index 0000000..912c23a
--- /dev/null
+++ b/tf_fuzz/demo/4
@@ -0,0 +1,2 @@
+purpose to show how to randomize data;
+set sst name gibberish data *;
diff --git a/tf_fuzz/demo/5 b/tf_fuzz/demo/5
new file mode 100644
index 0000000..5290f27
--- /dev/null
+++ b/tf_fuzz/demo/5
@@ -0,0 +1,2 @@
+purpose to show how to randomize name and data;
+set sst name * data *;
diff --git a/tf_fuzz/demo/6 b/tf_fuzz/demo/6
new file mode 100644
index 0000000..2e86d75
--- /dev/null
+++ b/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/tf_fuzz/demo/7 b/tf_fuzz/demo/7
new file mode 100644
index 0000000..903027e
--- /dev/null
+++ b/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/tf_fuzz/demo/8 b/tf_fuzz/demo/8
new file mode 100644
index 0000000..03b22d9
--- /dev/null
+++ b/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*" expect fail;
diff --git a/tf_fuzz/demo/9 b/tf_fuzz/demo/9
new file mode 100644
index 0000000..72cc269
--- /dev/null
+++ b/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/tf_fuzz/demo/README b/tf_fuzz/demo/README
new file mode 100644
index 0000000..4dc4bbe
--- /dev/null
+++ b/tf_fuzz/demo/README
@@ -0,0 +1,10 @@
+This directory contains some example usages of TF-Fuzz, in a form that makes it
+easy to run each case and quickly see the results.
+
+For more information, please browse to:
+
+ https://ci.trustedfirmware.org/job/tf-m-build-test-nightly/lastSuccessfulBuild/artifact/build-docs/tf-m_documents/install/doc/user_guide/html/docs/user_guides/tf_fuzz/demo_dir.html
+
+--------------
+
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
diff --git a/tf_fuzz/demo/chkgcc b/tf_fuzz/demo/chkgcc
new file mode 100644
index 0000000..fff9770
--- /dev/null
+++ b/tf_fuzz/demo/chkgcc
@@ -0,0 +1,14 @@
+echo
+echo "Check-compiling..."
+echo
+gcc -I../../../../trusted-firmware-m-backup/test/suites/sst \
+ -I../../../../trusted-firmware-m-backup/interface/include \
+ -I../../../../trusted-firmware-m-backup \
+ -I../../../../trusted-firmware-m-backup/test/suites/crypto \
+ -I../../../secure_fw/spm/include \
+ -I../../../../CMSIS_5/CMSIS/Core/Include \
+ -Werror -Wunused-variable \
+ -c tossThis.c
+echo
+echo "Check-compile complete."
+echo
diff --git a/tf_fuzz/demo/r b/tf_fuzz/demo/r
new file mode 100644
index 0000000..d9b8978
--- /dev/null
+++ b/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 tossThis.c
+../tfz -v $1 tossThis.c
diff --git a/tf_fuzz/docs/asset_dir.rst b/tf_fuzz/docs/asset_dir.rst
new file mode 100644
index 0000000..4eb358d
--- /dev/null
+++ b/tf_fuzz/docs/asset_dir.rst
@@ -0,0 +1,30 @@
+########################
+'assets'-directory guide
+########################
+
+************
+Introduction
+************
+
+This directory contains C++ header and program files for classes of objects that
+track PSA assets, while generating a directed-random test. Notably this is
+during the Simulate phase, after Parse phase, which parses the test-template
+file, and prior to writing out the generated C code.
+
+***********************************************
+``.../tools/tf_fuzz/assets`` directory contents
+***********************************************
+.. code-block:: bash
+
+ crypto_asset.cpp psa_asset.cpp sst_asset.cpp
+ crypto_asset.hpp psa_asset.hpp sst_asset.hpp
+
+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.
+Simulation only occurs to a level of detail of being able to predict pass/fail
+status, and asset data. Generally speaking, it does not simulate
+secure-partition code.
+
+--------------
+
+*Copyright (c) 2020, Arm Limited. All rights reserved.*
diff --git a/tf_fuzz/docs/boilerplate_dir.rst b/tf_fuzz/docs/boilerplate_dir.rst
new file mode 100644
index 0000000..d4aea0e
--- /dev/null
+++ b/tf_fuzz/docs/boilerplate_dir.rst
@@ -0,0 +1,27 @@
+#############################
+'boilerplate'-directory guide
+#############################
+
+************
+Introduction
+************
+
+This directory contains the C++ header and code files to work with the
+customizable, "boilerplate" code snippets in the ``...tools/tf_fuzz/lib``
+directory. Mostly what this code does is read these code snippets into an
+STL ``vector`` of, essentially, named strings.
+
+****************************************************
+``.../tools/tf_fuzz/boilerplate`` directory contents
+****************************************************
+.. code-block:: bash
+
+ boilerplate.cpp boilerplate.hpp
+
+This is currently implemented as a vector of strings, with a parallel vector
+of ``const int`` array-index names. (In the future, it may make sense to
+manage the boilerplate code in a C++ STL ``map``-type container.)
+
+--------------
+
+*Copyright (c) 2020, Arm Limited. All rights reserved.*
diff --git a/tf_fuzz/docs/calls_dir.rst b/tf_fuzz/docs/calls_dir.rst
new file mode 100644
index 0000000..17c2491
--- /dev/null
+++ b/tf_fuzz/docs/calls_dir.rst
@@ -0,0 +1,33 @@
+#######################
+'calls'-directory guide
+#######################
+
+************
+Introduction
+************
+
+These classes define objects that describe everything needed to generate a PSA
+call. The Parse phase, which parses the test-template file, generates an C++
+STL ``vector`` of ``psa_call``-class objects describing the series of PSA calls
+chosen for the test to run, based upon the test template and the random seed.
+
+More-specifically class psa_class is an abstract class, and this vector contains
+objects of derived classes, each derived class defining a particular call type.
+Each ``psa_call``-subclass object encapsulates the initial and expected data,
+expected pass/fail results, and other information about the call.
+
+**********************************************
+``.../tools/tf_fuzz/calls`` directory contents
+**********************************************
+.. code-block:: bash
+
+ crypto_call.cpp psa_call.cpp security_call.cpp sst_call.cpp
+ crypto_call.hpp psa_call.hpp security_call.hpp sst_call.hpp
+
+In the future, it's probably possible to, for target systems that can support
+sufficiently large memory footprints, instead of writing these calls out to a
+``.c`` file, to directly execute these PSA calls.
+
+--------------
+
+*Copyright (c) 2020, Arm Limited. All rights reserved.*
diff --git a/tf_fuzz/docs/demo_dir.rst b/tf_fuzz/docs/demo_dir.rst
new file mode 100644
index 0000000..fb49fe7
--- /dev/null
+++ b/tf_fuzz/docs/demo_dir.rst
@@ -0,0 +1,46 @@
+######################
+'demo'-directory guide
+######################
+
+************
+Introduction
+************
+
+This directory contains some example usages of TF-Fuzz, in a form that makes it
+easy to run each case and quickly see the results.
+
+An example way to use this directory:
+
+- Add ``./`` to your ``$PATH`` variable, for convenience (see below).
+- Using any text editor that provides for tabbed editing (e.g., Nedit) pop
+ up all files in this directory, each in a separate tab.
+- In a shell window, run each demo test, and view a file called
+ ``tossThis2`` (that name to suggest we delete that file after we're done)
+ to view the generated C code.
+
+The ``purpose`` line in each test describes what each demo illustrates.
+
+Bear in mind that these are not intended as practical use cases, but just for
+illustration. In the first few cases, the TF-Fuzz tool is not very "smart";
+that is, TF-Fuzz only provides a very-compact test-specification format. As
+the test number increases, the TF-Fuzz tool infers for you more about test.
+
+*********************************************
+``.../tools/tf_fuzz/demo`` directory contents
+*********************************************
+.. code-block:: bash
+
+ 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
+demonstrating 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 very short script name
+``r`` and the very-short, numbered demo-test file names were chosen to make it
+easy to quickly see example usages. To see sequentially more-involved usages
+of the tool, go through these demos in order.
+
+--------------
+
+*Copyright (c) 2020, Arm Limited. All rights reserved.*
diff --git a/tf_fuzz/docs/index.rst b/tf_fuzz/docs/index.rst
new file mode 100644
index 0000000..ee74714
--- /dev/null
+++ b/tf_fuzz/docs/index.rst
@@ -0,0 +1,13 @@
+TF-Fuzz
+=======
+
+.. toctree::
+ :maxdepth: 1
+ :caption: Contents
+ :glob:
+
+ *
+
+--------------
+
+*Copyright (c) 2020, Arm Limited. All rights reserved.*
diff --git a/tf_fuzz/docs/lib_dir.rst b/tf_fuzz/docs/lib_dir.rst
new file mode 100644
index 0000000..fbc54dd
--- /dev/null
+++ b/tf_fuzz/docs/lib_dir.rst
@@ -0,0 +1,33 @@
+#####################
+'lib'-directory guide
+#####################
+
+************
+Introduction
+************
+
+This directory contains the customizable "boilerplate" code snippets used to
+write out C source code. The file in this directory currently, is that for
+TF-M, but other comparable frameworks could be addressed with equivalent files
+taylored for the required syntax of that other framework.
+
+Which file to use for this process is selected by setting two environment
+variables pointing to that file: One for the ``lib`` directory and one for the
+file itself within that directory. In ``bash`` syntax,
+
+.. code-block:: bash
+
+ export TF_FUZZ_LIB_DIR=<path to this TF-M installation>/tools/tf_fuzz/lib
+ export TF_FUZZ_BPLATE=tfm_boilerplate.txt
+
+
+********************************************
+``.../tools/tf_fuzz/lib`` directory contents
+********************************************
+.. code-block:: bash
+
+ tfm_boilerplate.txt
+
+--------------
+
+*Copyright (c) 2020, Arm Limited. All rights reserved.*
diff --git a/tf_fuzz/docs/parser_dir.rst b/tf_fuzz/docs/parser_dir.rst
new file mode 100644
index 0000000..ddbca5a
--- /dev/null
+++ b/tf_fuzz/docs/parser_dir.rst
@@ -0,0 +1,27 @@
+########################
+'parser'-directory guide
+########################
+
+************
+Introduction
+************
+
+Users' test-template files are parsed using a Lex/YACC grammar, to make the
+test-template language easily extensible. Much of the actual work is done in
+helper functions, but the Lex/YACC grammar manages the process.
+
+***********************************************
+``.../tools/tf_fuzz/parser`` directory contents
+***********************************************
+.. code-block:: bash
+
+ 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) 2020, Arm Limited. All rights reserved.*
diff --git a/tf_fuzz/docs/regression_dir.rst b/tf_fuzz/docs/regression_dir.rst
new file mode 100644
index 0000000..ec4ea6d
--- /dev/null
+++ b/tf_fuzz/docs/regression_dir.rst
@@ -0,0 +1,169 @@
+############################
+'regression'-directory guide
+############################
+
+************
+Introduction
+************
+
+This is a regression suite for the TF-Fuzz tool. That is, tests to make sure
+that TF-Fuzz is still functioning properly after making changes. Note that
+this regression implementation tests the most basic aspects of TF-Fuzz's
+implementation, but is not yet complete. Most notably, it does not yet test
+``*active`` and ``*deleted``, nor ``shuffle`` and ``2 to 5 of {...}``
+constructs.
+
+***************************************************
+``.../tools/tf_fuzz/regression`` directory contents
+***************************************************
+.. code-block:: bash
+
+ 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
+ 000015_set_sst_name_only
+ 000016_set_sst_single_asset_set_multiple_times
+ 000017_read_sst_check_single_asset_multiple_times
+ 000018_000016_and_000017
+ 000019_read_asset_to_variable_set_other_asset
+ add_these_tests
+ function2OpenFiles
+ README
+ regress
+ regress_lib
+
+******************************
+Files for Each Regression Test
+******************************
+
+Here's the overall regression scheme:
+
+- ``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, 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 *actual* 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.
+
+ - ``check.py``: This Python 3 script compares expected to actual
+ ``stdout``/``stderr`` and C-test code, resolving wildcard references in
+ ``exp_stdout_stderr`` and ``exp_test.c``. Each test directory has its own
+ script customized to the needs of that particular test, but they mostly
+ just runs TF-Fuzz, opens files, then invokes functions in the
+ ``regress_lib`` directory, which do the majority of the actual work.
+
+********************************
+How ``check.py`` Assesses a Test
+********************************
+
+To illustrate how ``check.py`` checks a regression test, below is a ``diff`` of
+``test.c`` and ``exp_test.c`` file files, from
+``./000005_set_sst_rand_name_rand_data/``, at the time of writing this:
+
+.. code-block:: bash
+
+ 47,48c47,48
+ < static uint8_t koxjis_data[] = "Gaa wuqnoe xoq uhoz qof er uaycuuf?";
+ < static int koxjis_data_size = 35;
+ ---
+ > static uint8_t @@@003@@@_data[] = "@@002@10@@[a-z\ ]*[\.\?\!]";
+ > static int @@@003@@@_data_size = \d+;
+ 53,55c53,55
+ < /* Creating SST asset "koxjis," with data "Gaa wuqnoe...". */
+ < sst_status = psa_ps_set(2110, koxjis_data_size, koxjis_data,
+ < PSA_STORAGE_FLAG_NONE);
+ ---
+ > /* Creating SST asset "@@@003@@@," with data "@@002@10@@...". */
+ > sst_status = psa_ps_set(@@@001@@@, @@@003@@@_data_size, @@@003@@@_data,
+ > PSA_STORAGE_FLAG_[A-Z_]+);
+ 63c63
+ < psa_ps_remove(2110);
+ ---
+ > psa_ps_remove(@@@001@@@);
+
+``check.py``, short summary, performs a Python ``re.match()`` line-by-line the
+generated ``test.c`` against the ``exp_test.c`` file. However, ``exp_test.c``,
+in addition to Python regular expressions, also contains "special" wildcards,
+described below.
+
+*********
+Wildcards
+*********
+
+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):
+
+.. list-table::
+ :widths: 20 80
+
+ * - ``[a-z\ ]*[\.\?\!]`` or ``[A-Z_]+``
+ - | These are Python regex pattern matches for what characters are expected
+ | at those places. The data consist of quasi-sentences, capitalized at
+ | the beginning. The capitalized character is covered by the
+ | ``@@002@10@@`` (see below) before it. The ``[a-z\ ]*[\.\?\!]`` is a
+ | Python-regex match for all remaining characters of the sentence: A
+ | sequence of zero or more lower-case letters or blanks followed by
+ | sentence-ending punctuation.
+
+ * - ``@@@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 consistently match ``8617`` everywhere throughout the ``test.c``
+ | file. Of course, the ``8617`` is different for different random-seed
+ | values. The number between the two ``@@@`` occurrences 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 47 and 48 above, random data
+ | generated consists of 10 characters (thus the ... ``@10@@`` in the
+ | wildcard) ``Gaa wuqnoe`` followed by other characters we don't care
+ | about; they can be anything. Thus ``@@002@10@@[a-z\ ]*[\.\?\!]`` in
+ | line 47: The ``@@002@10@@`` denotes a pattern number 002 for a length
+ | of 10 characters that must match ``Gaa wuqnoe`` in this case, followed
+ | by some arbitrary number of characters we don't care about, thus
+ | ``[a-z\ ]*[\.\?\!]`` -- a sequence of lower-case letters or spaces,
+ | capped off with normal sentence-ending punctuation.
+
+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 ``5 to 8 of {}`` randomizations.
+
+The ``add_these_tests`` directory contains regression tests of the above nature
+that the regression framework is not currently able to address.
+
+--------------
+
+*Copyright (c) 2020, Arm Limited. All rights reserved.*
diff --git a/tf_fuzz/docs/template_dir.rst b/tf_fuzz/docs/template_dir.rst
new file mode 100644
index 0000000..86dbbfa
--- /dev/null
+++ b/tf_fuzz/docs/template_dir.rst
@@ -0,0 +1,23 @@
+##########################
+'template'-directory guide
+##########################
+
+************
+Introduction
+************
+
+These classes describe "tracker" objects for parsing test templates, and for
+generating PSA calls from them.
+
+*************************************************
+``.../tools/tf_fuzz/template`` directory contents
+*************************************************
+.. code-block:: bash
+
+ 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
+
+--------------
+
+*Copyright (c) 2020, Arm Limited. All rights reserved.*
diff --git a/tf_fuzz/docs/tests_dir.rst b/tf_fuzz/docs/tests_dir.rst
new file mode 100644
index 0000000..8226451
--- /dev/null
+++ b/tf_fuzz/docs/tests_dir.rst
@@ -0,0 +1,21 @@
+#######################
+'tests'-directory guide
+#######################
+
+************
+Introduction
+************
+
+These are just more examples of test-template-file content. They're not really
+organized *tests* as such.
+
+**********************************************
+``.../tools/tf_fuzz/tests`` directory contents
+**********************************************
+.. code-block:: bash
+
+ example_template sstReads sstSets
+
+--------------
+
+*Copyright (c) 2020, Arm Limited. All rights reserved.*
diff --git a/tf_fuzz/docs/tf_fuzz_dir.rst b/tf_fuzz/docs/tf_fuzz_dir.rst
new file mode 100644
index 0000000..6ad0a38
--- /dev/null
+++ b/tf_fuzz/docs/tf_fuzz_dir.rst
@@ -0,0 +1,124 @@
+#######################################
+TF-Fuzz (Trusted-Firmware Fuzzer) guide
+#######################################
+
+************
+Introduction
+************
+
+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 all be viewable by all parties.)
+
+To build TF-Fuzz, simply type ``make`` in this directory. The executable,
+called ``tfz``, is placed in this directory.
+
+To run ``tfz``, two environment variables must first be assigned. In bash
+syntax:
+
+.. code-block:: bash
+
+ 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.
+
+**********************************
+``.../tf_fuzz`` directory contents
+**********************************
+.. code-block:: bash
+
+ assets calls demo parser tests regression
+ backupStuff class_forwards.hpp lib document tf_fuzz.cpp utility
+ boilerplate commands Makefile template tf_fuzz.hpp visualStudio
+
+*************
+Code Overview
+*************
+To help understand the code, below is a C++-class hierarchy used in this code
+base. They are explained further in the documents in their respective
+directories, 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):
+
+.. code-block:: bash
+
+ 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
+ init_policy_call ./calls/crypto_call.hpp
+ reset_policy_call ./calls/crypto_call.hpp
+ add_policy_usage_call ./calls/crypto_call.hpp
+ set_policy_lifetime_call ./calls/crypto_call.hpp
+ set_policy_type_call ./calls/crypto_call.hpp
+ set_policy_algorithm_call ./calls/crypto_call.hpp
+ set_policy_usage_call ./calls/crypto_call.hpp
+ get_policy_lifetime_call ./calls/crypto_call.hpp
+ get_policy_type_call ./calls/crypto_call.hpp
+ get_policy_algorithm_call ./calls/crypto_call.hpp
+ get_policy_usage_call ./calls/crypto_call.hpp
+ get_policy_size_call ./calls/crypto_call.hpp
+ get_policy_call ./calls/crypto_call.hpp
+ key_call ./calls/crypto_call.hpp
+ generate_key_call ./calls/crypto_call.hpp
+ create_key_call ./calls/crypto_call.hpp
+ copy_key_call ./calls/crypto_call.hpp
+ read_key_data_call ./calls/crypto_call.hpp
+ remove_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
+
+ variables ./utility/variables.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
+
+TF-Fuzz now has better-organized management of variables in the generated code.
+In particular, it maintains a list of variables named in the test template, and
+implicit in the code, notably variables assets are ``read`` into. It also now has
+completely separate execution phases to parse the test template, simulate the
+sequence of PSA calls generated, and write out the expected results. That
+simulation is only in enough detail to predict expected results. Since TF-Fuzz
+currectly mostly addresses only SST calls, that simulation is very simple in
+nature -- just tracking data movement.
+
+--------------
+
+*Copyright (c) 2020, Arm Limited. All rights reserved.*
diff --git a/tf_fuzz/docs/utility_dir.rst b/tf_fuzz/docs/utility_dir.rst
new file mode 100644
index 0000000..89ad060
--- /dev/null
+++ b/tf_fuzz/docs/utility_dir.rst
@@ -0,0 +1,24 @@
+#########################
+'utility'-directory guide
+#########################
+
+************
+Introduction
+************
+
+As its name implies, this ``.../tf_fuzz/utility`` directory just contains
+various utility-compute code.
+
+************************************************
+``.../tools/tf_fuzz/utility`` directory contents
+************************************************
+.. code-block:: bash
+
+ 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
+
+--------------
+
+*Copyright (c) 2020, Arm Limited. All rights reserved.*
diff --git a/tf_fuzz/docs/visualStudio_dir.rst b/tf_fuzz/docs/visualStudio_dir.rst
new file mode 100644
index 0000000..a70bbf8
--- /dev/null
+++ b/tf_fuzz/docs/visualStudio_dir.rst
@@ -0,0 +1,26 @@
+##############################
+'visualStudio'-directory guide
+##############################
+
+************
+Introduction
+************
+
+This is just things to support running and debug under Microsoft Visual Studio
+(Visual Studio is a trademark of Microsoft Corporation). 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 and YACC. Other
+functions may be added later as needed. At some time in the future, an
+up-coming "interactive mode" for interactively creating test templates may
+need an actual working ``isatty()``, but that's not ready yet.
+
+*************************************************
+.../tools/tf_fuzz/visualStudio directory contents
+*************************************************
+.. code-block:: bash
+
+ unistd.c unistd.h
+
+--------------
+
+*Copyright (c) 2020, Arm Limited. All rights reserved.*
diff --git a/tf_fuzz/generate_test_suite.sh b/tf_fuzz/generate_test_suite.sh
new file mode 100755
index 0000000..80e0b38
--- /dev/null
+++ b/tf_fuzz/generate_test_suite.sh
@@ -0,0 +1,209 @@
+#!/usr/bin/env bash
+#
+# Copyright (c) 2020-2021, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+set -e
+
+SUITE_DIR_NAME=tfm_fuzz
+
+show_help()
+{
+ echo "Usage: $0 <template_dir> <suites_dir> "
+ echo ""
+ echo "Where: "
+ echo " template_dir: The directory containing template files for the"
+ echo " fuzzing tool"
+ echo " suites_dir: The directory to generate the test suite to."
+}
+
+if [ $# != 2 ]
+then
+ echo "Invalid number of parameters."
+ show_help
+ exit 1
+fi
+
+INPUT_DIR=$1
+SUITES_DIR=$2
+
+# Check that the input directory exists
+if [ ! -d "$INPUT_DIR" ]
+then
+ echo "Template directory '$INPUT_DIR' doesn't exist"
+ exit 1
+fi
+
+# Check that the input directory contains files
+if [ `ls "$INPUT_DIR"| wc -l` == 0 ]
+then
+ echo "Template directory '$INPUT_DIR' doesn't contain files"
+ exit 1
+fi
+
+if [ ! -d "$SUITES_DIR" ]
+then
+ echo "Suites directory '$SUITES_DIR' doesn't exist"
+ exit 1
+fi
+
+# Check whether a fuzz test suite was generated before
+if [ -d "$SUITES_DIR/$SUITE_DIR_NAME" ]
+then
+ echo "'$SUITE_DIR_NAME' exists."
+ echo "A TF fuzz test suite is already generated, please delete it before running this script"
+ exit 1
+fi
+
+#get absolute path of the suit dir TF_FUZZ
+pushd $SUITES_DIR > /dev/null
+SUITE_ABSOLUTE_DIR=`pwd`/$SUITE_DIR_NAME
+popd
+
+# creating directory for the fuzz tests tool
+echo "Creating '$SUITES_DIR/$SUITE_DIR_NAME/non_secure'"
+mkdir -p $SUITES_DIR/$SUITE_DIR_NAME/non_secure
+
+# generate additional files for the suite:
+CMAKELIST=$SUITES_DIR/$SUITE_DIR_NAME/CMakeLists.txt
+TESTSUITE=$SUITES_DIR/$SUITE_DIR_NAME/non_secure/tf_fuzz_testsuite.c
+TESTSUITE_HEADER=$SUITES_DIR/$SUITE_DIR_NAME/non_secure/tf_fuzz_testsuite.h
+
+# generate data for the testcases
+# Iterate over the testcase files and
+# - Run the fuzzer on the test template
+# - Generate a test function name, and replace the generic test_thread to that
+# in the generated c file
+# - append the generated c file to the CmakeList file.
+declare -A FILENAMES
+declare -A FUNC_NAMES
+declare -A PURPOSES
+for f in `ls $INPUT_DIR`
+do
+ FILE="$SUITES_DIR/$SUITE_DIR_NAME/non_secure/$f.c"
+ FILENAMES[$f]=$FILE
+
+ SEED=$RANDOM
+ echo "Generating testcase $f with seed $SEED"
+ ./tfz -z $INPUT_DIR/$f $FILE $SEED
+
+ echo "in File ${FILENAMES[$f]}"
+
+ PURPOSE=`grep -A 1 'Test purpose' $FILE | tail -n 1 | cut -d '*' -f 2 | sed -e 's/^[[:space:]]*//'`
+ PURPOSES[$f]=$PURPOSE
+
+ FUNC_NAME="$PURPOSE"
+ FUNC_NAME=`echo "$FUNC_NAME" | \
+ sed 's/^\s*//g; s/\s*$//g; s/\s\s*/_/g'`
+ FUNC_NAME=`echo "$FUNC_NAME" | \
+ sed 's/\-/_/g; s/"//g; s/\\\//g'`
+ FUNC_NAME=`echo "$FUNC_NAME" | \
+ sed "s/#//g; s/'//g; s/,//g; s/(//g; s/)//g"`
+ FUNC_NAMES[$f]=$FUNC_NAME
+
+ echo " Changing 'test_thread' to '${FUNC_NAMES[$f]}'"
+
+ sed -i "s/test_thread/$FUNC_NAME/g" $FILE
+
+done
+
+# generate the non-secure testsuite file
+echo '#include <stdio.h>' >> $TESTSUITE
+echo '#include <string.h>' >> $TESTSUITE
+echo '' >> $TESTSUITE
+echo '#include "tfm_api.h"' >> $TESTSUITE
+echo '#include "psa_manifest/sid.h"' >> $TESTSUITE
+echo '#include "test_framework.h"' >> $TESTSUITE
+echo '' >> $TESTSUITE
+echo '/* Forward declaring static test functions */' >> $TESTSUITE
+for f in `ls $INPUT_DIR`
+do
+ echo "static void test_${FUNC_NAMES[$f]}(struct test_result_t *ret);" >> $TESTSUITE
+done
+echo '/* Forward declaring functions */' >> $TESTSUITE
+for f in `ls $INPUT_DIR`
+do
+ echo "void ${FUNC_NAMES[$f]}(struct test_result_t *ret);" >> $TESTSUITE
+done
+echo '' >> $TESTSUITE
+echo 'static struct test_t tf_fuzz_tests[] = {' >> $TESTSUITE
+for f in `ls $INPUT_DIR`
+do
+ echo " {&test_${FUNC_NAMES[$f]}, \"${FUNC_NAMES[$f]}\", \"${PURPOSES[$f]}\", {0} }," >> $TESTSUITE
+done
+echo '}; ' >> $TESTSUITE
+echo '' >> $TESTSUITE
+echo 'void register_testsuite_tf_fuzz_test(struct test_suite_t *p_test_suite)' >> $TESTSUITE
+echo '{' >> $TESTSUITE
+echo ' uint32_t list_size;' >> $TESTSUITE
+echo '' >> $TESTSUITE
+echo ' list_size = (sizeof(tf_fuzz_tests) / sizeof(tf_fuzz_tests[0]));' >> $TESTSUITE
+echo '' >> $TESTSUITE
+echo ' set_testsuite("TF-M fuzz tests (TF_FUZZ_TEST)",' >> $TESTSUITE
+echo ' tf_fuzz_tests, list_size, p_test_suite);' >> $TESTSUITE
+echo '}' >> $TESTSUITE
+echo '' >> $TESTSUITE
+for f in `ls $INPUT_DIR`
+do
+ echo "static void test_${FUNC_NAMES[$f]}(struct test_result_t *ret)" >> $TESTSUITE
+ echo '{' >> $TESTSUITE
+ echo " ${FUNC_NAMES[$f]}(ret);" >> $TESTSUITE
+ echo ' if (ret->val != TEST_PASSED) {' >> $TESTSUITE
+ echo ' return;' >> $TESTSUITE
+ echo ' }' >> $TESTSUITE
+ echo '' >> $TESTSUITE
+ echo '}' >> $TESTSUITE
+done
+
+# generate the CmakeList file
+echo "cmake_policy(SET CMP0079 NEW)" >> $CMAKELIST
+echo "" >> $CMAKELIST
+echo "add_library(tfm_test_suite_tf_fuzz_ns STATIC EXCLUDE_FROM_ALL)" >> $CMAKELIST
+echo "" >> $CMAKELIST
+echo "target_sources(tfm_test_suite_tf_fuzz_ns" >> $CMAKELIST
+echo " PRIVATE" >> $CMAKELIST
+for f in `ls $INPUT_DIR`
+do
+ echo " $SUITE_ABSOLUTE_DIR/non_secure/$f.c" >> $CMAKELIST
+done
+echo " $SUITE_ABSOLUTE_DIR/non_secure/tf_fuzz_testsuite.c" >> $CMAKELIST
+echo ")" >> $CMAKELIST
+echo "" >> $CMAKELIST
+echo "target_include_directories(tfm_test_suite_tf_fuzz_ns" >> $CMAKELIST
+echo " PUBLIC" >> $CMAKELIST
+echo " ./non_secure" >> $CMAKELIST
+echo " PRIVATE" >> $CMAKELIST
+echo " ." >> $CMAKELIST
+echo ")" >> $CMAKELIST
+echo "" >> $CMAKELIST
+echo "target_link_libraries(tfm_test_suite_tf_fuzz_ns" >> $CMAKELIST
+echo " PRIVATE" >> $CMAKELIST
+echo " tfm_test_framework_ns" >> $CMAKELIST
+echo " tfm_test_suite_its_ns" >> $CMAKELIST
+echo ")" >> $CMAKELIST
+echo "" >> $CMAKELIST
+echo "target_link_libraries(tfm_ns_tests" >> $CMAKELIST
+echo " INTERFACE" >> $CMAKELIST
+echo " tfm_test_suite_tf_fuzz_ns" >> $CMAKELIST
+echo ")" >> $CMAKELIST
+
+# generate the testsuite header file
+echo '#ifndef __PSA_API_FUZZ_TESTSUITE_H__' >> $TESTSUITE_HEADER
+echo '#define __PSA_API_FUZZ_TESTSUITE_H__' >> $TESTSUITE_HEADER
+echo '' >> $TESTSUITE_HEADER
+echo 'void register_testsuite_tf_fuzz_test(struct test_suite_t *p_test_suite);' >> $TESTSUITE_HEADER
+echo '' >> $TESTSUITE_HEADER
+echo '#endif /* __PSA_API_FUZZ_TESTSUITE_H__ */' >> $TESTSUITE_HEADER
+
+# print some instruction on the screen
+echo ''
+echo ''
+echo '========================================================================='
+echo '= The test suite generation is done. It can be compiled to TF-M by'
+echo '= providing the following options to the CMake generate command:'
+echo '='
+echo '= -DTFM_FUZZER_TOOL_TESTS=1'
+echo '= -DTFM_FUZZER_TOOL_TESTS_CMAKE_INC_PATH='$SUITE_ABSOLUTE_DIR
+echo '========================================================================='
diff --git a/tf_fuzz/lib/README b/tf_fuzz/lib/README
new file mode 100644
index 0000000..7c46edc
--- /dev/null
+++ b/tf_fuzz/lib/README
@@ -0,0 +1,10 @@
+This directory contains the customizable "boilerplate" code snippets used to
+write out C source code.
+
+For more information, please browse to:
+
+ https://ci.trustedfirmware.org/job/tf-m-build-test-nightly/lastSuccessfulBuild/artifact/build-docs/tf-m_documents/install/doc/user_guide/html/docs/user_guides/tf_fuzz/lib_dir.html
+
+--------------
+
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
diff --git a/tf_fuzz/lib/human_boilerplate.txt b/tf_fuzz/lib/human_boilerplate.txt
new file mode 100644
index 0000000..f475902
--- /dev/null
+++ b/tf_fuzz/lib/human_boilerplate.txt
@@ -0,0 +1,194 @@
+/*
+ * 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 used to create a human-readable summary of the actual code. It's
+not exactly documentation as such, but more of just a human-oriented flow of the
+generated test code.
+
+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 Check 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.
+`000
+This test is intended:
+ $purpose.
+
+ It starts with essential #include directives.
+`001
+
+ The code continues with declaration and definitions of helper functions
+ that perform a simple hashing of data. This hash allows many different
+ blocks of data to be compared to each other in all combinations. Nominally
+ this is to find data leaks between variables.
+`002
+
+ Next is a declaration of the thread function that performs the generated
+ test, then...
+
+`003 `004
+ Declaration of int-type variable called $var, with initial value "$init"
+`005
+ Declaration of uint8_t unchanging array, $var, with initial value of:
+ $init
+`006
+ Declaration of uint8_t array, $var, with initial value of:
+ $init
+ A lot of space is given to this array anticipating that it will be over-
+ written with potentially large read-data.
+`007
+ Declaration of size_t-type variable called $var,
+ with initial value "$init".
+`008
+ Declaration of psa_key_attributes_t-type variable called $var.
+`009
+ Declaration of psa_algorithm_t-type variable called $var.
+`010
+ Declaration of psa_key_lifetime_t-type variable called $var.
+`011
+ Declaration of psa_key_type_t-type variable $var;
+`012
+ Declaration of psa_key_usage_t-type variable $var;
+`013
+ Declaration of psa_key_handle_t-type variable $var;
+`014
+ Declaration of $type-type variable called $var, with initial value "$init".
+`015
+
+ Writing to the message log:
+ $message.
+`016
+
+ Test-teardown delete of SST asset UID $uid.
+`017
+ Verify that the previous call was successful.
+`018
+
+ Test-teardown delete of key asset, handle "$handle."
+`019
+ Verify that the previous call was successful.
+`020
+
+And this is the end of the test.
+`021 PSA_SUCCESS`022 PSA_ERROR_DOES_NOT_EXIST`023
+
+ Set an SST asset:
+ * UID = $uid, length = $length,
+ * data = $data, and
+ * creation flags = $flags.
+`024
+ Verify that previous had a result of $expect.
+`025
+
+ Read (get) SST-asset data:
+ * UID = $uid, length = $length,
+ * actual data in $act_data, and
+ * actual length in $act_length.
+`026
+ Verify that previous had a result of $expect.
+`027
+ Verify that the previous SST get (read) had a result of "$expect,"
+ then a comparison of the values read, $act_data against $exp_data.
+`028
+ Hash the SST data in $act_data_var for later data-leak check,
+ resulting has being placed in $hash_var. */
+`029
+
+ Deletion of SST asset, UID = $uid.
+`030
+ Verify that previous SST-asset deletion had a result of $expect.
+`031
+ Initializing PSA-Crypto attributes (policy) "$policy".
+`032
+ Resetting key attributes (policy) for "$policy".
+`033
+ Adding a key-policy attribute of $flag to "$policy".
+`034
+ Setting key-policy "$policy"'s lifetime to $life.
+`035
+ Setting the key size for "$policy" to $size bits.
+`036
+ Setting the key type for "$policy" to $type.
+`037
+ Setting the key algorithm for "$policy" to $algorithm.
+`038
+ Setting key usage flags for "$policy" to $usage.
+`039
+ Reading key lifetime for "$policy" into variable $life.
+`040
+ Reading key lifetime for "$policy" into variable $life,
+ and displaying it to the log file.
+
+`041
+ Reading key size into variable $size, for key policy "$policy".
+`042
+ Reading key type into variable $type, for key policy "$policy".
+`043
+ Reading key type into variable $type, for key policy "$policy",
+ and displaying it to the log file.
+`044
+ Reading key algorithm into variable $algorithm, for key policy "$policy".
+`045
+ Reading key algorithm into variable $algorithm, for key policy "$policy",
+ and displaying it to the log file.
+`046
+ Reading key usage into variable $usage, for key policy "$policy".
+`047
+ Displaying to the log the presence or not of key-policy usage
+ $usage_string for key-policy "$policy",
+ as either $print_usage_true_string or $print_usage_false_string.
+`048
+ Reading attributes (policy) for key $key into variable "$policy".
+`049
+ Verify that previous get (read) of key policies had result of $expect.
+`050
+ Generate key (no key data specified) $key, from policy "$policy".
+`051
+ Verify that previous key generation had result of $expect.
+`052
+ Creating key for key $key:
+ * Policy = "$policy",
+ * Data variable = $data, and
+ * Length = $length.
+`053
+ Verify that key-creation had result of $expect.
+`054
+ Copying a key:
+ * Master key = $master,
+ * Copy key = $copy, and
+ * New-key policy = "$policy".
+`055
+ Verify that key-export (read of key data) had result of $expect.
+`056
+ Verify that key-data read into $act_data, matches dat in $exp_data.
+`057
+ Export (read) of key data for $key:
+ * Data variable = $data,
+ * Data-length variable = $length, and
+ * Actual data-size variable = $act_size.
+`058
+ Verify that key-export (read of key data) had result of $expect.
+`059
+ Delete key $key.
+`060
+ Verify that key-delete had result of $expect.
+`
diff --git a/tf_fuzz/lib/tfm_boilerplate.txt b/tf_fuzz/lib/tfm_boilerplate.txt
new file mode 100644
index 0000000..dcec086
--- /dev/null
+++ b/tf_fuzz/lib/tfm_boilerplate.txt
@@ -0,0 +1,289 @@
+/*
+ * 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.
+`000
+/*
+ * Test purpose:
+ * $purpose
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "psa/protected_storage.h"
+#include "psa/crypto.h"
+#include "test_framework.h"
+`001
+
+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;
+`003
+ (void)sst_status;
+ /* "void" to prevent unused-variable warning, since the variable may not
+ * be used in this particular test case.
+ */
+
+ crypto_status = psa_crypto_init();
+ if (crypto_status != PSA_SUCCESS) {
+ TEST_FAIL("Could not initialize Crypto.");
+ return;
+ }
+
+ TEST_LOG("Test $purpose");
+`004
+ static int $var = $init;
+`005
+ static uint8_t $var[] = "$init";
+`006
+ static uint8_t $var[2048] = "$init";
+`007
+ static size_t $var = $init;
+`008
+ static psa_key_attributes_t $var;
+`009
+ static psa_algorithm_t $var;
+`010
+ static psa_key_lifetime_t $var;
+`011
+ static psa_key_type_t $var;
+`012
+ static psa_key_usage_t $var;
+`013
+ static psa_key_handle_t $var;
+`014
+ $type $var = $init;
+`015
+ TEST_LOG("$message");
+`016
+ psa_ps_remove($uid);
+`017
+ if (sst_status != PSA_SUCCESS) {
+ TEST_FAIL("Failed to tear down an SST asset upon test completion.");
+ return;
+ }
+`018
+ psa_destroy_key($handle);
+`019
+ if (crypto_status != PSA_SUCCESS) {
+ TEST_FAIL("Failed to tear down a crypto asset upon test completion");
+ return;
+ }
+`020
+
+ /* Test completed */
+ ret->val = TEST_PASSED;
+}
+`021 PSA_SUCCESS`022 PSA_ERROR_DOES_NOT_EXIST`023
+ /* $op SST asset $description with data $data_source. */
+ sst_status = psa_ps_set($uid, $length, $data,
+ $flags);
+`024
+ if (sst_status != $expect) {
+ TEST_FAIL("psa_ps_set() expected $expect.");
+ return;
+ }
+`025
+ sst_status = psa_ps_get($uid, $offset, $length, $act_data,
+ &$act_length);
+`026
+ if (sst_status != $expect) {
+ TEST_FAIL("psa_ps_get() expected $expect.");
+ return;
+ }
+`027
+ if (sst_status != $expect) {
+ TEST_FAIL("psa_ps_get() expected $expect.");
+ return;
+ }
+ /* Check that the data is correct */
+ if (memcmp($act_data, $exp_data,
+ $length) != 0) {
+ TEST_FAIL("Read data should be equal to result data");
+ return;
+ }
+`028
+ /* 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; */
+`029
+ sst_status = psa_ps_remove($uid);
+`030
+ if (sst_status != $expect) {
+ TEST_FAIL("psa_ps_remove() expected $expect.");
+ return;
+ }
+`031
+ $policy = psa_key_attributes_init();
+`032
+ psa_reset_key_attributes (&$policy);
+`033
+ psa_set_key_usage_flags (
+ &$policy,
+ psa_get_key_usage_flags (&$policy)
+ | $flag
+ );
+`034
+ psa_set_key_lifetime (&$policy, $life);
+`035
+ psa_set_key_bits (&$policy, $size);
+`036
+ psa_set_key_type (&$policy, $type);
+`037
+ psa_set_key_algorithm (&$policy, $algorithm);
+`038
+ psa_set_key_usage_flags (&$policy, $usage);
+`039
+ $life = psa_get_key_lifetime (&$policy);
+`040
+ $life = psa_get_key_lifetime (&$policy);
+ if ($life == PSA_KEY_LIFETIME_VOLATILE) {
+ TEST_LOG("$policy: Lifetime is volatile.");
+ } else {
+ TEST_LOG("$policy: Lifetime is persistent.");
+ }
+`041
+ $size = psa_get_key_bits (&$policy);
+`042
+ $type = psa_get_key_type (&$policy);
+`043
+ $type = psa_get_key_type (&$policy);
+ TEST_LOG("$policy: Key-type code == $type.");
+`044
+ $algorithm = psa_get_key_algorithm (&$policy);
+`045
+ $algorithm = psa_get_key_algorithm (&$policy);
+ TEST_LOG("$policy: Key-algorithm code == $algorithm.");
+`046
+ $usage = psa_get_key_usage_flags (&$policy);
+`047
+ if (($usage & $usage_string) != 0) {
+ TEST_LOG("$policy: $print_usage_true_string.");
+ } else {
+ TEST_LOG("$policy: $print_usage_false_string.");
+ }
+`048
+ crypto_status = psa_get_key_attributes ($key, &$policy);
+`049
+ if (crypto_status != $expect) {
+ TEST_FAIL("psa_get_key_attributes() expected $expect.");
+ return;
+ }
+`050
+ crypto_status = psa_generate_key (&$policy, &$key);
+`051
+ if (crypto_status != $expect) {
+ TEST_FAIL("psa_generate_key() expected $expect.");
+ return;
+ }
+`052
+ crypto_status
+ = psa_import_key (&$policy, $data, $length, &$key);
+`053
+ if (crypto_status != $expect) {
+ TEST_FAIL("psa_import_key() expected $expect.");
+ return;
+ }
+`054
+ crypto_status = psa_copy_key ($master, &$policy, &$copy);
+`055
+ if (crypto_status != $expect) {
+ TEST_FAIL("psa_copy_key() expected $expect.");
+ return;
+ }
+`056
+ /* Check that the data is correct */
+ if (memcmp($act_data, $exp_data,
+ $length) != 0) {
+ TEST_FAIL("Read data should be equal to result data");
+ return;
+ }
+`057
+ crypto_status
+ = psa_export_key ($key, $data, $length, &$act_size);
+`058
+ if (crypto_status != $expect) {
+ TEST_FAIL("psa_export_key() expected $expect.");
+ return;
+ }
+`059
+ crypto_status = psa_destroy_key($key);
+`060
+ if (crypto_status != $expect) {
+ TEST_FAIL("psa_destroy_key() expected $expect.");
+ return;
+ }
+`
diff --git a/tf_fuzz/parser/README b/tf_fuzz/parser/README
new file mode 100644
index 0000000..8301488
--- /dev/null
+++ b/tf_fuzz/parser/README
@@ -0,0 +1,10 @@
+This directory contains the Lex and YACC grammars for parsing the TF-Fuzz command
+"language" (if it can be called a language as such).
+
+For more information, please browse to:
+
+ https://ci.trustedfirmware.org/job/tf-m-build-test-nightly/lastSuccessfulBuild/artifact/build-docs/tf-m_documents/install/doc/user_guide/html/docs/user_guides/tf_fuzz/parser_dir.html
+
+--------------
+
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
diff --git a/tf_fuzz/parser/tf_fuzz_grammar.l b/tf_fuzz/parser/tf_fuzz_grammar.l
new file mode 100644
index 0000000..429e60c
--- /dev/null
+++ b/tf_fuzz/parser/tf_fuzz_grammar.l
@@ -0,0 +1,165 @@
+/*
+ * 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;
+rm return REMOVE;
+secure return SECURE;
+sec return SECURE;
+done return DONE;
+ /* PSA-asset types: */
+sst return SST;
+key return KEY;
+policy return POLICY;
+ /* Other root-command operands: */
+expect return EXPECT;
+exp return EXPECT;
+pass return PASS;
+fail return FAIL;
+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;
+act return ACTIVE;
+deleted return DELETED;
+del return DELETED;
+removed return DELETED;
+check return CHECK;
+chk return CHECK;
+var return VAR;
+print return PRINT;
+hash return HASH;
+neq return NEQ;
+dfname return DFNAME;
+shuffle return SHUFFLE;
+shuf return SHUFFLE;
+to return TO;
+of return OF;
+ /* SST creation keywords: */
+flag return FLAG;
+none return NONE;
+write_once return WRITE_ONCE;
+wo return WRITE_ONCE;
+no_rp return NO_RP;
+nrp return NO_RP;
+no_conf return NO_CONF;
+ncf return NO_CONF;
+ /* Offset into an SST asset */
+offset return OFFSET;
+ /* Policy keywords: */
+attributes return ATTR;
+attr return ATTR;
+type return TYPE;
+algorithm return ALG;
+alg return ALG;
+ /* Policy-usage and -lifetime keywords: */
+export return EXPORT;
+exp return EXPORT;
+noexport return NOEXPORT;
+nex return NOEXPORT;
+copy return COPY;
+nocopy return NOCOPY;
+encrypt return ENCRYPT;
+encr return ENCRYPT;
+noencrypt return NOENCRYPT;
+nenc return NOENCRYPT;
+decrypt return DECRYPT;
+decr return DECRYPT;
+nodecrypt return NODECRYPT;
+ndecr return NODECRYPT;
+sign return SIGN;
+nosign return NOSIGN;
+verify return VERIFY;
+ver return VERIFY;
+noverify return NOVERIFY;
+nver return NOVERIFY;
+derive return DERIVE;
+der return DERIVE;
+noderive return NODERIVE;
+nder return NODERIVE;
+persistent return PERSISTENT;
+pers return PERSISTENT;
+volatile return VOLATILE;
+vol return VOLATILE;
+from return FROM;
+with return WITH;
+ /* 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;}
+\[[a-fA-F 0-9]*\] {yylval.str = yytext; return HEX_LIST;}
+ /* inside quotes: anything but a quote, or nothing */
+[ \t\n\r] ; /* ignore white space */
+. yyerror ((tf_fuzz_info *) NULL, "Unexpected character");
+
+%%
+
diff --git a/tf_fuzz/parser/tf_fuzz_grammar.lex.c b/tf_fuzz/parser/tf_fuzz_grammar.lex.c
new file mode 100644
index 0000000..48c715b
--- /dev/null
+++ b/tf_fuzz/parser/tf_fuzz_grammar.lex.c
@@ -0,0 +1,2548 @@
+#line 2 "parser/tf_fuzz_grammar.lex.c"
+
+#line 4 "parser/tf_fuzz_grammar.lex.c"
+
+#define YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 6
+#define YY_FLEX_SUBMINOR_VERSION 0
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types.
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t;
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX (4294967295U)
+#endif
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif /* defined (__STDC__) */
+#endif /* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index. If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN (yy_start) = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart(yyin )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
+#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+extern yy_size_t yyleng;
+
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+ /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
+ * access to the local variable yy_act. Since yyless() is a macro, it would break
+ * existing scanners that call yyless() from OUTSIDE yylex.
+ * One obvious solution it to make yy_act a global. I tried that, and saw
+ * a 5% performance hit in a non-yylineno scanner, because yy_act is
+ * normally declared as a register variable-- so it is not worth it.
+ */
+ #define YY_LESS_LINENO(n) \
+ do { \
+ int yyl;\
+ for ( yyl = n; yyl < yyleng; ++yyl )\
+ if ( yytext[yyl] == '\n' )\
+ --yylineno;\
+ }while(0)
+ #define YY_LINENO_REWIND_TO(dst) \
+ do {\
+ const char *p;\
+ for ( p = yy_cp-1; p >= (dst); --p)\
+ if ( *p == '\n' )\
+ --yylineno;\
+ }while(0)
+
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ *yy_cp = (yy_hold_char); \
+ YY_RESTORE_YY_MORE_OFFSET \
+ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+ } \
+ while ( 0 )
+
+#define unput(c) yyunput( c, (yytext_ptr) )
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ int yy_bs_lineno; /**< The line count. */
+ int yy_bs_column; /**< The column count. */
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via yyrestart()), so that the user can continue scanning by
+ * just pointing yyin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+
+ };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+ : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+static int yy_n_chars; /* number of characters read into yy_ch_buf */
+yy_size_t yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 0; /* whether we need to initialize */
+static int yy_start = 0; /* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin. A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart (FILE *input_file );
+void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer );
+YY_BUFFER_STATE yy_create_buffer (FILE *file,int size );
+void yy_delete_buffer (YY_BUFFER_STATE b );
+void yy_flush_buffer (YY_BUFFER_STATE b );
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer );
+void yypop_buffer_state (void );
+
+static void yyensure_buffer_stack (void );
+static void yy_load_buffer_state (void );
+static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file );
+
+#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size );
+YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str );
+YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len );
+
+void *yyalloc (yy_size_t );
+void *yyrealloc (void *,yy_size_t );
+void yyfree (void * );
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){ \
+ yyensure_buffer_stack (); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ yy_create_buffer(yyin,YY_BUF_SIZE ); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+ }
+
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){\
+ yyensure_buffer_stack (); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ yy_create_buffer(yyin,YY_BUF_SIZE ); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+ }
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define yywrap() (/*CONSTCOND*/1)
+#define YY_SKIP_YYWRAP
+
+typedef unsigned char YY_CHAR;
+
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+
+typedef int yy_state_type;
+
+extern int yylineno;
+
+int yylineno = 1;
+
+extern char yytext[];
+
+static yy_state_type yy_get_previous_state (void );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state );
+static int yy_get_next_buffer (void );
+#if defined(__GNUC__) && __GNUC__ >= 3
+__attribute__((__noreturn__))
+#endif
+static void yy_fatal_error (yyconst char msg[] );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ (yytext_ptr) = yy_bp; \
+ yyleng = (size_t) (yy_cp - yy_bp); \
+ (yy_hold_char) = *yy_cp; \
+ *yy_cp = '\0'; \
+ if ( yyleng >= YYLMAX ) \
+ YY_FATAL_ERROR( "token too large, exceeds YYLMAX" ); \
+ yy_flex_strncpy( yytext, (yytext_ptr), yyleng + 1 ); \
+ (yy_c_buf_p) = yy_cp;
+
+#define YY_NUM_RULES 98
+#define YY_END_OF_BUFFER 99
+/* This struct is not used in this scanner,
+ but its presence is necessary. */
+struct yy_trans_info
+ {
+ flex_int32_t yy_verify;
+ flex_int32_t yy_nxt;
+ };
+static yyconst flex_int16_t yy_accept[310] =
+ { 0,
+ 92, 92, 0, 0, 99, 97, 96, 96, 1, 97,
+ 97, 30, 92, 97, 92, 26, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 24, 25, 7, 6, 7, 0,
+ 94, 0, 92, 4, 0, 91, 0, 91, 95, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 46, 91, 91, 91, 91, 91, 91,
+ 11, 91, 91, 91, 91, 45, 91, 91, 91, 91,
+ 91, 91, 50, 91, 5, 93, 0, 2, 32, 60,
+
+ 91, 91, 37, 91, 91, 91, 34, 82, 91, 91,
+ 91, 91, 19, 91, 91, 91, 91, 16, 91, 54,
+ 91, 91, 41, 64, 91, 91, 91, 91, 91, 91,
+ 91, 91, 52, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 13, 8, 91, 91, 15, 91, 28, 38,
+ 78, 88, 91, 91, 91, 91, 57, 91, 65, 29,
+ 72, 91, 91, 91, 14, 68, 91, 91, 91, 21,
+ 47, 89, 40, 27, 91, 84, 70, 91, 91, 91,
+ 91, 91, 91, 48, 91, 91, 91, 80, 91, 20,
+ 86, 91, 91, 91, 9, 91, 91, 44, 75, 58,
+
+ 91, 91, 90, 91, 91, 91, 91, 36, 91, 91,
+ 91, 91, 91, 23, 91, 91, 74, 91, 51, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 39, 91, 91, 91, 91, 91, 91, 91, 31, 91,
+ 91, 91, 91, 81, 42, 91, 18, 61, 91, 66,
+ 91, 91, 91, 91, 76, 91, 91, 55, 91, 17,
+ 91, 10, 12, 91, 77, 91, 91, 91, 91, 71,
+ 33, 67, 53, 91, 91, 91, 91, 22, 91, 91,
+ 91, 35, 43, 91, 91, 91, 91, 91, 83, 91,
+ 63, 79, 91, 0, 87, 91, 59, 91, 73, 69,
+
+ 91, 0, 0, 3, 91, 56, 85, 49, 0
+ } ;
+
+static yyconst YY_CHAR yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 1, 1, 4, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 5, 1, 6, 1, 1, 1, 1, 7, 1,
+ 1, 8, 9, 1, 9, 10, 11, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 1, 13, 1,
+ 1, 1, 1, 1, 14, 14, 14, 14, 14, 14,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 16, 17, 18, 17, 19, 17, 20, 21, 22, 23,
+
+ 24, 25, 26, 27, 28, 15, 29, 30, 31, 32,
+ 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+ 43, 15, 44, 1, 45, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+ } ;
+
+static yyconst YY_CHAR yy_meta[46] =
+ { 0,
+ 1, 1, 1, 1, 2, 1, 1, 1, 1, 3,
+ 3, 4, 1, 4, 5, 1, 1, 2, 5, 4,
+ 4, 4, 4, 4, 4, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 1, 1
+ } ;
+
+static yyconst flex_uint16_t yy_base[317] =
+ { 0,
+ 0, 0, 43, 44, 359, 360, 360, 360, 360, 352,
+ 0, 360, 345, 42, 344, 360, 0, 49, 26, 22,
+ 55, 26, 46, 335, 330, 69, 328, 61, 53, 59,
+ 65, 324, 79, 78, 360, 360, 360, 360, 340, 344,
+ 360, 342, 336, 360, 344, 0, 328, 0, 360, 307,
+ 318, 305, 36, 308, 303, 85, 308, 307, 316, 301,
+ 302, 307, 314, 300, 295, 288, 299, 304, 304, 78,
+ 103, 293, 302, 300, 287, 287, 292, 293, 284, 70,
+ 0, 94, 280, 292, 279, 0, 282, 292, 278, 277,
+ 282, 273, 0, 282, 360, 360, 306, 360, 280, 274,
+
+ 270, 283, 0, 261, 283, 266, 277, 272, 279, 274,
+ 261, 263, 71, 265, 268, 262, 265, 0, 267, 0,
+ 95, 268, 0, 0, 97, 256, 264, 86, 263, 258,
+ 258, 260, 0, 247, 245, 244, 243, 251, 246, 243,
+ 253, 242, 235, 0, 248, 240, 0, 247, 0, 0,
+ 242, 249, 241, 229, 226, 229, 236, 234, 0, 0,
+ 219, 223, 220, 228, 0, 215, 221, 234, 219, 0,
+ 0, 0, 0, 0, 218, 0, 0, 220, 218, 217,
+ 101, 228, 215, 0, 222, 219, 210, 0, 221, 0,
+ 216, 221, 204, 208, 0, 200, 203, 213, 0, 0,
+
+ 212, 198, 0, 211, 210, 205, 211, 0, 197, 206,
+ 205, 204, 193, 0, 188, 187, 0, 192, 0, 180,
+ 186, 193, 184, 186, 186, 185, 188, 177, 177, 170,
+ 0, 175, 187, 186, 179, 165, 179, 187, 0, 167,
+ 165, 165, 179, 0, 0, 163, 0, 0, 175, 0,
+ 156, 158, 154, 160, 0, 169, 169, 0, 155, 0,
+ 168, 168, 0, 166, 0, 159, 155, 160, 148, 0,
+ 0, 0, 0, 151, 160, 143, 116, 0, 109, 127,
+ 134, 0, 0, 126, 117, 117, 122, 100, 0, 96,
+ 0, 0, 98, 140, 0, 107, 0, 87, 0, 0,
+
+ 40, 46, 142, 360, 33, 0, 0, 0, 360, 155,
+ 160, 163, 165, 170, 174, 178
+ } ;
+
+static yyconst flex_int16_t yy_def[317] =
+ { 0,
+ 309, 1, 310, 310, 309, 309, 309, 309, 309, 311,
+ 312, 309, 309, 309, 309, 309, 313, 313, 313, 313,
+ 313, 313, 313, 313, 313, 313, 313, 313, 313, 313,
+ 313, 313, 313, 313, 309, 309, 309, 309, 309, 311,
+ 309, 312, 309, 309, 314, 313, 315, 18, 309, 313,
+ 313, 313, 313, 313, 313, 313, 313, 313, 313, 313,
+ 313, 313, 313, 313, 313, 313, 313, 313, 313, 313,
+ 313, 313, 313, 313, 313, 313, 313, 313, 313, 313,
+ 313, 313, 313, 313, 313, 313, 313, 313, 313, 313,
+ 313, 313, 313, 313, 309, 309, 314, 309, 313, 313,
+
+ 313, 313, 313, 313, 313, 313, 313, 313, 313, 313,
+ 313, 313, 313, 313, 313, 313, 313, 313, 313, 313,
+ 313, 313, 313, 313, 313, 313, 313, 313, 313, 313,
+ 313, 313, 313, 313, 313, 313, 313, 313, 313, 313,
+ 313, 313, 313, 313, 313, 313, 313, 313, 313, 313,
+ 313, 313, 313, 313, 313, 313, 313, 313, 313, 313,
+ 313, 313, 313, 313, 313, 313, 313, 313, 313, 313,
+ 313, 313, 313, 313, 313, 313, 313, 313, 313, 313,
+ 313, 313, 313, 313, 313, 313, 313, 313, 313, 313,
+ 313, 313, 313, 313, 313, 313, 313, 313, 313, 313,
+
+ 313, 313, 313, 313, 313, 313, 313, 313, 313, 313,
+ 313, 313, 313, 313, 313, 313, 313, 313, 313, 313,
+ 313, 313, 313, 313, 313, 313, 313, 313, 313, 313,
+ 313, 313, 313, 313, 313, 313, 313, 313, 313, 313,
+ 313, 313, 313, 313, 313, 313, 313, 313, 313, 313,
+ 313, 313, 313, 313, 313, 313, 313, 313, 313, 313,
+ 313, 313, 313, 313, 313, 313, 313, 313, 313, 313,
+ 313, 313, 313, 313, 313, 313, 313, 313, 313, 313,
+ 313, 313, 313, 313, 313, 313, 313, 313, 313, 313,
+ 313, 313, 313, 316, 313, 313, 313, 313, 313, 313,
+
+ 313, 316, 316, 309, 313, 313, 313, 313, 0, 309,
+ 309, 309, 309, 309, 309, 309
+ } ;
+
+static yyconst flex_uint16_t yy_nxt[406] =
+ { 0,
+ 6, 7, 8, 9, 7, 10, 11, 12, 13, 6,
+ 14, 15, 16, 17, 17, 18, 17, 17, 17, 19,
+ 17, 20, 21, 22, 23, 17, 24, 17, 25, 17,
+ 17, 26, 27, 28, 17, 29, 30, 31, 32, 33,
+ 34, 17, 17, 35, 36, 38, 38, 50, 53, 44,
+ 39, 39, 45, 47, 54, 51, 308, 59, 304, 102,
+ 48, 60, 48, 52, 103, 62, 49, 61, 48, 48,
+ 48, 48, 48, 48, 55, 63, 80, 307, 56, 57,
+ 75, 64, 82, 81, 76, 83, 84, 58, 67, 141,
+ 68, 69, 70, 77, 168, 85, 78, 86, 89, 79,
+
+ 142, 71, 90, 169, 72, 92, 106, 87, 73, 122,
+ 93, 91, 123, 94, 107, 143, 175, 182, 178, 124,
+ 108, 125, 221, 306, 126, 127, 128, 183, 305, 301,
+ 176, 144, 179, 300, 129, 294, 222, 299, 294, 130,
+ 131, 303, 132, 303, 303, 298, 303, 297, 296, 295,
+ 293, 292, 304, 291, 304, 37, 37, 37, 37, 37,
+ 40, 40, 40, 40, 40, 42, 42, 42, 46, 46,
+ 97, 97, 97, 97, 97, 47, 290, 47, 302, 302,
+ 302, 302, 302, 289, 288, 287, 286, 285, 284, 283,
+ 282, 281, 280, 279, 278, 277, 276, 275, 274, 273,
+
+ 272, 271, 270, 269, 268, 267, 266, 265, 264, 263,
+ 262, 261, 260, 259, 258, 257, 256, 255, 254, 253,
+ 252, 251, 250, 249, 248, 247, 246, 245, 244, 243,
+ 242, 241, 240, 239, 238, 237, 236, 235, 234, 233,
+ 232, 231, 230, 229, 228, 227, 226, 225, 224, 223,
+ 220, 219, 218, 217, 216, 215, 214, 213, 212, 211,
+ 210, 209, 208, 207, 206, 205, 204, 203, 202, 201,
+ 200, 199, 198, 197, 196, 195, 194, 193, 192, 191,
+ 190, 189, 188, 187, 186, 185, 184, 181, 180, 177,
+ 174, 173, 172, 171, 170, 167, 166, 165, 164, 163,
+
+ 162, 161, 160, 159, 158, 157, 156, 155, 98, 154,
+ 153, 152, 151, 150, 149, 148, 147, 146, 145, 140,
+ 139, 138, 137, 136, 135, 134, 133, 121, 120, 119,
+ 118, 117, 116, 115, 114, 113, 112, 111, 110, 109,
+ 105, 104, 101, 100, 99, 49, 98, 43, 96, 41,
+ 95, 88, 74, 66, 65, 43, 43, 41, 309, 5,
+ 309, 309, 309, 309, 309, 309, 309, 309, 309, 309,
+ 309, 309, 309, 309, 309, 309, 309, 309, 309, 309,
+ 309, 309, 309, 309, 309, 309, 309, 309, 309, 309,
+ 309, 309, 309, 309, 309, 309, 309, 309, 309, 309,
+
+ 309, 309, 309, 309, 309
+ } ;
+
+static yyconst flex_int16_t yy_chk[406] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 3, 4, 19, 20, 14,
+ 3, 4, 14, 18, 20, 19, 305, 22, 302, 53,
+ 18, 22, 18, 19, 53, 23, 18, 22, 18, 18,
+ 18, 18, 18, 18, 21, 23, 29, 301, 21, 21,
+ 28, 23, 30, 29, 28, 30, 30, 21, 26, 80,
+ 26, 26, 26, 28, 113, 30, 28, 31, 33, 28,
+
+ 80, 26, 33, 113, 26, 34, 56, 31, 26, 70,
+ 34, 33, 70, 34, 56, 82, 121, 128, 125, 70,
+ 56, 71, 181, 298, 71, 71, 71, 128, 296, 293,
+ 121, 82, 125, 290, 71, 281, 181, 288, 281, 71,
+ 71, 294, 71, 303, 294, 287, 303, 286, 285, 284,
+ 280, 279, 294, 277, 303, 310, 310, 310, 310, 310,
+ 311, 311, 311, 311, 311, 312, 312, 312, 313, 313,
+ 314, 314, 314, 314, 314, 315, 276, 315, 316, 316,
+ 316, 316, 316, 275, 274, 269, 268, 267, 266, 264,
+ 262, 261, 259, 257, 256, 254, 253, 252, 251, 249,
+
+ 246, 243, 242, 241, 240, 238, 237, 236, 235, 234,
+ 233, 232, 230, 229, 228, 227, 226, 225, 224, 223,
+ 222, 221, 220, 218, 216, 215, 213, 212, 211, 210,
+ 209, 207, 206, 205, 204, 202, 201, 198, 197, 196,
+ 194, 193, 192, 191, 189, 187, 186, 185, 183, 182,
+ 180, 179, 178, 175, 169, 168, 167, 166, 164, 163,
+ 162, 161, 158, 157, 156, 155, 154, 153, 152, 151,
+ 148, 146, 145, 143, 142, 141, 140, 139, 138, 137,
+ 136, 135, 134, 132, 131, 130, 129, 127, 126, 122,
+ 119, 117, 116, 115, 114, 112, 111, 110, 109, 108,
+
+ 107, 106, 105, 104, 102, 101, 100, 99, 97, 94,
+ 92, 91, 90, 89, 88, 87, 85, 84, 83, 79,
+ 78, 77, 76, 75, 74, 73, 72, 69, 68, 67,
+ 66, 65, 64, 63, 62, 61, 60, 59, 58, 57,
+ 55, 54, 52, 51, 50, 47, 45, 43, 42, 40,
+ 39, 32, 27, 25, 24, 15, 13, 10, 5, 309,
+ 309, 309, 309, 309, 309, 309, 309, 309, 309, 309,
+ 309, 309, 309, 309, 309, 309, 309, 309, 309, 309,
+ 309, 309, 309, 309, 309, 309, 309, 309, 309, 309,
+ 309, 309, 309, 309, 309, 309, 309, 309, 309, 309,
+
+ 309, 309, 309, 309, 309
+ } ;
+
+/* Table of booleans, true if rule could match eol. */
+static yyconst flex_int32_t yy_rule_can_match_eol[99] =
+ { 0,
+0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, };
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+extern int yy_flex_debug;
+int yy_flex_debug = 0;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+#ifndef YYLMAX
+#define YYLMAX 8192
+#endif
+
+char yytext[YYLMAX];
+char *yytext_ptr;
+#line 1 "parser/tf_fuzz_grammar.l"
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#line 10 "parser/tf_fuzz_grammar.l"
+#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
+
+
+#line 738 "parser/tf_fuzz_grammar.lex.c"
+
+#define INITIAL 0
+#define BLOCK_COMMENT 1
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+static int yy_init_globals (void );
+
+/* Accessor methods to globals.
+ These are made visible to non-reentrant scanners for convenience. */
+
+int yylex_destroy (void );
+
+int yyget_debug (void );
+
+void yyset_debug (int debug_flag );
+
+YY_EXTRA_TYPE yyget_extra (void );
+
+void yyset_extra (YY_EXTRA_TYPE user_defined );
+
+FILE *yyget_in (void );
+
+void yyset_in (FILE * _in_str );
+
+FILE *yyget_out (void );
+
+void yyset_out (FILE * _out_str );
+
+yy_size_t yyget_leng (void );
+
+char *yyget_text (void );
+
+int yyget_lineno (void );
+
+void yyset_lineno (int _line_number );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap (void );
+#else
+extern int yywrap (void );
+#endif
+#endif
+
+#ifndef YY_NO_UNPUT
+
+ static void yyunput (int c,char *buf_ptr );
+
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (void );
+#else
+static int input (void );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
+#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+ { \
+ int c = '*'; \
+ size_t n; \
+ for ( n = 0; n < max_size && \
+ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+ buf[n] = (char) c; \
+ if ( c == '\n' ) \
+ buf[n++] = (char) c; \
+ if ( c == EOF && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ result = n; \
+ } \
+ else \
+ { \
+ errno=0; \
+ while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+ { \
+ if( errno != EINTR) \
+ { \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ break; \
+ } \
+ errno=0; \
+ clearerr(yyin); \
+ } \
+ }\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int yylex (void);
+
+#define YY_DECL int yylex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK /*LINTED*/break;
+#endif
+
+#define YY_RULE_SETUP \
+ YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+ yy_state_type yy_current_state;
+ char *yy_cp, *yy_bp;
+ int yy_act;
+
+ if ( !(yy_init) )
+ {
+ (yy_init) = 1;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ if ( ! (yy_start) )
+ (yy_start) = 1; /* first start state */
+
+ if ( ! yyin )
+ yyin = stdin;
+
+ if ( ! yyout )
+ yyout = stdout;
+
+ if ( ! YY_CURRENT_BUFFER ) {
+ yyensure_buffer_stack ();
+ YY_CURRENT_BUFFER_LVALUE =
+ yy_create_buffer(yyin,YY_BUF_SIZE );
+ }
+
+ yy_load_buffer_state( );
+ }
+
+ {
+#line 55 "parser/tf_fuzz_grammar.l"
+
+
+#line 960 "parser/tf_fuzz_grammar.lex.c"
+
+ while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = (yy_c_buf_p);
+
+ /* Support of yytext. */
+ *yy_cp = (yy_hold_char);
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = (yy_start);
+yy_match:
+ do
+ {
+ YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
+ if ( yy_accept[yy_current_state] )
+ {
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 310 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ ++yy_cp;
+ }
+ while ( yy_base[yy_current_state] != 360 );
+
+yy_find_action:
+ yy_act = yy_accept[yy_current_state];
+ if ( yy_act == 0 )
+ { /* have to back up */
+ yy_cp = (yy_last_accepting_cpos);
+ yy_current_state = (yy_last_accepting_state);
+ yy_act = yy_accept[yy_current_state];
+ }
+
+ YY_DO_BEFORE_ACTION;
+
+ if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
+ {
+ yy_size_t yyl;
+ for ( yyl = 0; yyl < yyleng; ++yyl )
+ if ( yytext[yyl] == '\n' )
+
+ yylineno++;
+;
+ }
+
+do_action: /* This label is used only to access EOF actions. */
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+ case 0: /* must back up */
+ /* undo the effects of YY_DO_BEFORE_ACTION */
+ *yy_cp = (yy_hold_char);
+ yy_cp = (yy_last_accepting_cpos);
+ yy_current_state = (yy_last_accepting_state);
+ goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 57 "parser/tf_fuzz_grammar.l"
+; /* ignore all \r */
+ YY_BREAK
+case 2:
+/* rule 2 can match eol */
+YY_RULE_SETUP
+#line 58 "parser/tf_fuzz_grammar.l"
+; /* ignore C++-style line comments */
+ YY_BREAK
+case 3:
+/* rule 3 can match eol */
+YY_RULE_SETUP
+#line 59 "parser/tf_fuzz_grammar.l"
+return PURPOSE;
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 60 "parser/tf_fuzz_grammar.l"
+{BEGIN(BLOCK_COMMENT);}
+ YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 61 "parser/tf_fuzz_grammar.l"
+{BEGIN(INITIAL);}
+ YY_BREAK
+case 6:
+/* rule 6 can match eol */
+YY_RULE_SETUP
+#line 62 "parser/tf_fuzz_grammar.l"
+;
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 63 "parser/tf_fuzz_grammar.l"
+;
+ YY_BREAK
+/* Root commands: */
+case 8:
+YY_RULE_SETUP
+#line 65 "parser/tf_fuzz_grammar.l"
+return SET;
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 66 "parser/tf_fuzz_grammar.l"
+return READ;
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 67 "parser/tf_fuzz_grammar.l"
+return REMOVE;
+ YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 68 "parser/tf_fuzz_grammar.l"
+return REMOVE;
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 69 "parser/tf_fuzz_grammar.l"
+return SECURE;
+ YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 70 "parser/tf_fuzz_grammar.l"
+return SECURE;
+ YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 71 "parser/tf_fuzz_grammar.l"
+return DONE;
+ YY_BREAK
+/* PSA-asset types: */
+case 15:
+YY_RULE_SETUP
+#line 73 "parser/tf_fuzz_grammar.l"
+return SST;
+ YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 74 "parser/tf_fuzz_grammar.l"
+return KEY;
+ YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 75 "parser/tf_fuzz_grammar.l"
+return POLICY;
+ YY_BREAK
+/* Other root-command operands: */
+case 18:
+YY_RULE_SETUP
+#line 77 "parser/tf_fuzz_grammar.l"
+return EXPECT;
+ YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 78 "parser/tf_fuzz_grammar.l"
+return EXPECT;
+ YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 79 "parser/tf_fuzz_grammar.l"
+return PASS;
+ YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 80 "parser/tf_fuzz_grammar.l"
+return FAIL;
+ YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 81 "parser/tf_fuzz_grammar.l"
+return NOTHING;
+ YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 82 "parser/tf_fuzz_grammar.l"
+return ERROR;
+ YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 83 "parser/tf_fuzz_grammar.l"
+return OPEN_BRACE;
+ YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 84 "parser/tf_fuzz_grammar.l"
+return CLOSE_BRACE;
+ YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 85 "parser/tf_fuzz_grammar.l"
+return SEMICOLON;
+ YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 86 "parser/tf_fuzz_grammar.l"
+return NAME;
+ YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 87 "parser/tf_fuzz_grammar.l"
+return UID;
+ YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 88 "parser/tf_fuzz_grammar.l"
+return DATA;
+ YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 89 "parser/tf_fuzz_grammar.l"
+return STAR;
+ YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 90 "parser/tf_fuzz_grammar.l"
+return ACTIVE;
+ YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 91 "parser/tf_fuzz_grammar.l"
+return ACTIVE;
+ YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 92 "parser/tf_fuzz_grammar.l"
+return DELETED;
+ YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 93 "parser/tf_fuzz_grammar.l"
+return DELETED;
+ YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 94 "parser/tf_fuzz_grammar.l"
+return DELETED;
+ YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 95 "parser/tf_fuzz_grammar.l"
+return CHECK;
+ YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 96 "parser/tf_fuzz_grammar.l"
+return CHECK;
+ YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 97 "parser/tf_fuzz_grammar.l"
+return VAR;
+ YY_BREAK
+case 39:
+YY_RULE_SETUP
+#line 98 "parser/tf_fuzz_grammar.l"
+return PRINT;
+ YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 99 "parser/tf_fuzz_grammar.l"
+return HASH;
+ YY_BREAK
+case 41:
+YY_RULE_SETUP
+#line 100 "parser/tf_fuzz_grammar.l"
+return NEQ;
+ YY_BREAK
+case 42:
+YY_RULE_SETUP
+#line 101 "parser/tf_fuzz_grammar.l"
+return DFNAME;
+ YY_BREAK
+case 43:
+YY_RULE_SETUP
+#line 102 "parser/tf_fuzz_grammar.l"
+return SHUFFLE;
+ YY_BREAK
+case 44:
+YY_RULE_SETUP
+#line 103 "parser/tf_fuzz_grammar.l"
+return SHUFFLE;
+ YY_BREAK
+case 45:
+YY_RULE_SETUP
+#line 104 "parser/tf_fuzz_grammar.l"
+return TO;
+ YY_BREAK
+case 46:
+YY_RULE_SETUP
+#line 105 "parser/tf_fuzz_grammar.l"
+return OF;
+ YY_BREAK
+/* SST creation keywords: */
+case 47:
+YY_RULE_SETUP
+#line 107 "parser/tf_fuzz_grammar.l"
+return FLAG;
+ YY_BREAK
+case 48:
+YY_RULE_SETUP
+#line 108 "parser/tf_fuzz_grammar.l"
+return NONE;
+ YY_BREAK
+case 49:
+YY_RULE_SETUP
+#line 109 "parser/tf_fuzz_grammar.l"
+return WRITE_ONCE;
+ YY_BREAK
+case 50:
+YY_RULE_SETUP
+#line 110 "parser/tf_fuzz_grammar.l"
+return WRITE_ONCE;
+ YY_BREAK
+case 51:
+YY_RULE_SETUP
+#line 111 "parser/tf_fuzz_grammar.l"
+return NO_RP;
+ YY_BREAK
+case 52:
+YY_RULE_SETUP
+#line 112 "parser/tf_fuzz_grammar.l"
+return NO_RP;
+ YY_BREAK
+case 53:
+YY_RULE_SETUP
+#line 113 "parser/tf_fuzz_grammar.l"
+return NO_CONF;
+ YY_BREAK
+case 54:
+YY_RULE_SETUP
+#line 114 "parser/tf_fuzz_grammar.l"
+return NO_CONF;
+ YY_BREAK
+/* Offset into an SST asset */
+case 55:
+YY_RULE_SETUP
+#line 116 "parser/tf_fuzz_grammar.l"
+return OFFSET;
+ YY_BREAK
+/* Policy keywords: */
+case 56:
+YY_RULE_SETUP
+#line 118 "parser/tf_fuzz_grammar.l"
+return ATTR;
+ YY_BREAK
+case 57:
+YY_RULE_SETUP
+#line 119 "parser/tf_fuzz_grammar.l"
+return ATTR;
+ YY_BREAK
+case 58:
+YY_RULE_SETUP
+#line 120 "parser/tf_fuzz_grammar.l"
+return TYPE;
+ YY_BREAK
+case 59:
+YY_RULE_SETUP
+#line 121 "parser/tf_fuzz_grammar.l"
+return ALG;
+ YY_BREAK
+case 60:
+YY_RULE_SETUP
+#line 122 "parser/tf_fuzz_grammar.l"
+return ALG;
+ YY_BREAK
+/* Policy-usage and -lifetime keywords: */
+case 61:
+YY_RULE_SETUP
+#line 124 "parser/tf_fuzz_grammar.l"
+return EXPORT;
+ YY_BREAK
+case 62:
+YY_RULE_SETUP
+#line 125 "parser/tf_fuzz_grammar.l"
+return EXPORT;
+ YY_BREAK
+case 63:
+YY_RULE_SETUP
+#line 126 "parser/tf_fuzz_grammar.l"
+return NOEXPORT;
+ YY_BREAK
+case 64:
+YY_RULE_SETUP
+#line 127 "parser/tf_fuzz_grammar.l"
+return NOEXPORT;
+ YY_BREAK
+case 65:
+YY_RULE_SETUP
+#line 128 "parser/tf_fuzz_grammar.l"
+return COPY;
+ YY_BREAK
+case 66:
+YY_RULE_SETUP
+#line 129 "parser/tf_fuzz_grammar.l"
+return NOCOPY;
+ YY_BREAK
+case 67:
+YY_RULE_SETUP
+#line 130 "parser/tf_fuzz_grammar.l"
+return ENCRYPT;
+ YY_BREAK
+case 68:
+YY_RULE_SETUP
+#line 131 "parser/tf_fuzz_grammar.l"
+return ENCRYPT;
+ YY_BREAK
+case 69:
+YY_RULE_SETUP
+#line 132 "parser/tf_fuzz_grammar.l"
+return NOENCRYPT;
+ YY_BREAK
+case 70:
+YY_RULE_SETUP
+#line 133 "parser/tf_fuzz_grammar.l"
+return NOENCRYPT;
+ YY_BREAK
+case 71:
+YY_RULE_SETUP
+#line 134 "parser/tf_fuzz_grammar.l"
+return DECRYPT;
+ YY_BREAK
+case 72:
+YY_RULE_SETUP
+#line 135 "parser/tf_fuzz_grammar.l"
+return DECRYPT;
+ YY_BREAK
+case 73:
+YY_RULE_SETUP
+#line 136 "parser/tf_fuzz_grammar.l"
+return NODECRYPT;
+ YY_BREAK
+case 74:
+YY_RULE_SETUP
+#line 137 "parser/tf_fuzz_grammar.l"
+return NODECRYPT;
+ YY_BREAK
+case 75:
+YY_RULE_SETUP
+#line 138 "parser/tf_fuzz_grammar.l"
+return SIGN;
+ YY_BREAK
+case 76:
+YY_RULE_SETUP
+#line 139 "parser/tf_fuzz_grammar.l"
+return NOSIGN;
+ YY_BREAK
+case 77:
+YY_RULE_SETUP
+#line 140 "parser/tf_fuzz_grammar.l"
+return VERIFY;
+ YY_BREAK
+case 78:
+YY_RULE_SETUP
+#line 141 "parser/tf_fuzz_grammar.l"
+return VERIFY;
+ YY_BREAK
+case 79:
+YY_RULE_SETUP
+#line 142 "parser/tf_fuzz_grammar.l"
+return NOVERIFY;
+ YY_BREAK
+case 80:
+YY_RULE_SETUP
+#line 143 "parser/tf_fuzz_grammar.l"
+return NOVERIFY;
+ YY_BREAK
+case 81:
+YY_RULE_SETUP
+#line 144 "parser/tf_fuzz_grammar.l"
+return DERIVE;
+ YY_BREAK
+case 82:
+YY_RULE_SETUP
+#line 145 "parser/tf_fuzz_grammar.l"
+return DERIVE;
+ YY_BREAK
+case 83:
+YY_RULE_SETUP
+#line 146 "parser/tf_fuzz_grammar.l"
+return NODERIVE;
+ YY_BREAK
+case 84:
+YY_RULE_SETUP
+#line 147 "parser/tf_fuzz_grammar.l"
+return NODERIVE;
+ YY_BREAK
+case 85:
+YY_RULE_SETUP
+#line 148 "parser/tf_fuzz_grammar.l"
+return PERSISTENT;
+ YY_BREAK
+case 86:
+YY_RULE_SETUP
+#line 149 "parser/tf_fuzz_grammar.l"
+return PERSISTENT;
+ YY_BREAK
+case 87:
+YY_RULE_SETUP
+#line 150 "parser/tf_fuzz_grammar.l"
+return VOLATILE;
+ YY_BREAK
+case 88:
+YY_RULE_SETUP
+#line 151 "parser/tf_fuzz_grammar.l"
+return VOLATILE;
+ YY_BREAK
+case 89:
+YY_RULE_SETUP
+#line 152 "parser/tf_fuzz_grammar.l"
+return FROM;
+ YY_BREAK
+case 90:
+YY_RULE_SETUP
+#line 153 "parser/tf_fuzz_grammar.l"
+return WITH;
+ YY_BREAK
+/* Structure operands: */
+case 91:
+YY_RULE_SETUP
+#line 155 "parser/tf_fuzz_grammar.l"
+{yylval.str = yytext; return IDENTIFIER_TOK;}
+ YY_BREAK
+case 92:
+YY_RULE_SETUP
+#line 156 "parser/tf_fuzz_grammar.l"
+{yylval.valueN = atol(yytext); return NUMBER_TOK;}
+ YY_BREAK
+case 93:
+YY_RULE_SETUP
+#line 157 "parser/tf_fuzz_grammar.l"
+{yylval.str = yytext; return FILE_PATH_TOK;}
+ YY_BREAK
+case 94:
+/* rule 94 can match eol */
+YY_RULE_SETUP
+#line 158 "parser/tf_fuzz_grammar.l"
+{yylval.str = yytext; return LITERAL_TOK;}
+ YY_BREAK
+case 95:
+YY_RULE_SETUP
+#line 159 "parser/tf_fuzz_grammar.l"
+{yylval.str = yytext; return HEX_LIST;}
+ YY_BREAK
+/* inside quotes: anything but a quote, or nothing */
+case 96:
+/* rule 96 can match eol */
+YY_RULE_SETUP
+#line 161 "parser/tf_fuzz_grammar.l"
+; /* ignore white space */
+ YY_BREAK
+case 97:
+YY_RULE_SETUP
+#line 162 "parser/tf_fuzz_grammar.l"
+yyerror ((tf_fuzz_info *) NULL, "Unexpected character");
+ YY_BREAK
+case 98:
+YY_RULE_SETUP
+#line 164 "parser/tf_fuzz_grammar.l"
+YY_FATAL_ERROR( "flex scanner jammed" );
+ YY_BREAK
+#line 1531 "parser/tf_fuzz_grammar.lex.c"
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(BLOCK_COMMENT):
+ yyterminate();
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = (yy_hold_char);
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed yyin at a new source and called
+ * yylex(). If so, then we have to assure
+ * consistency between YY_CURRENT_BUFFER and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( );
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++(yy_c_buf_p);
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = (yy_c_buf_p);
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer( ) )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ (yy_did_buffer_switch_on_eof) = 0;
+
+ if ( yywrap( ) )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * yytext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! (yy_did_buffer_switch_on_eof) )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ (yy_c_buf_p) =
+ (yytext_ptr) + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( );
+
+ yy_cp = (yy_c_buf_p);
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ (yy_c_buf_p) =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+ yy_current_state = yy_get_previous_state( );
+
+ yy_cp = (yy_c_buf_p);
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+ } /* end of user's declarations */
+} /* end of yylex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (void)
+{
+ char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ char *source = (yytext_ptr);
+ yy_size_t number_to_move, i;
+ int ret_val;
+
+ if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (yy_size_t) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+ else
+ {
+ yy_size_t num_to_read =
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+
+ /* just a shorter name for the current buffer */
+ YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;
+
+ int yy_c_buf_p_offset =
+ (int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+ if ( b->yy_is_our_buffer )
+ {
+ yy_size_t new_size = b->yy_buf_size * 2;
+
+ if ( new_size <= 0 )
+ b->yy_buf_size += b->yy_buf_size / 8;
+ else
+ b->yy_buf_size *= 2;
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+ yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 );
+ }
+ else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = 0;
+
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow" );
+
+ (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+ num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+ number_to_move - 1;
+
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+ (yy_n_chars), num_to_read );
+
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ if ( (yy_n_chars) == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ yyrestart(yyin );
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ if ((int) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+ /* Extend the array by 50%, plus the number we really need. */
+ int new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size );
+ if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+ }
+
+ (yy_n_chars) += number_to_move;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+ (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+ return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+ static yy_state_type yy_get_previous_state (void)
+{
+ yy_state_type yy_current_state;
+ char *yy_cp;
+
+ yy_current_state = (yy_start);
+
+ for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+ {
+ YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ if ( yy_accept[yy_current_state] )
+ {
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 310 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ }
+
+ return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state )
+{
+ int yy_is_jam;
+ char *yy_cp = (yy_c_buf_p);
+
+ YY_CHAR yy_c = 1;
+ if ( yy_accept[yy_current_state] )
+ {
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 310 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ yy_is_jam = (yy_current_state == 309);
+
+ return yy_is_jam ? 0 : yy_current_state;
+}
+
+#ifndef YY_NO_UNPUT
+
+ static void yyunput (int c, char * yy_bp )
+{
+ char *yy_cp;
+
+ yy_cp = (yy_c_buf_p);
+
+ /* undo effects of setting up yytext */
+ *yy_cp = (yy_hold_char);
+
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ { /* need to shift things up to make room */
+ /* +2 for EOB chars. */
+ yy_size_t number_to_move = (yy_n_chars) + 2;
+ char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+ char *source =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+ while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ *--dest = *--source;
+
+ yy_cp += (int) (dest - source);
+ yy_bp += (int) (dest - source);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ YY_FATAL_ERROR( "flex scanner push-back overflow" );
+ }
+
+ *--yy_cp = (char) c;
+
+ if ( c == '\n' ){
+ --yylineno;
+ }
+
+ (yytext_ptr) = yy_bp;
+ (yy_hold_char) = *yy_cp;
+ (yy_c_buf_p) = yy_cp;
+}
+
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+ static int yyinput (void)
+#else
+ static int input (void)
+#endif
+
+{
+ int c;
+
+ *(yy_c_buf_p) = (yy_hold_char);
+
+ if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+ /* This was really a NUL. */
+ *(yy_c_buf_p) = '\0';
+
+ else
+ { /* need more input */
+ yy_size_t offset = (yy_c_buf_p) - (yytext_ptr);
+ ++(yy_c_buf_p);
+
+ switch ( yy_get_next_buffer( ) )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ yyrestart(yyin );
+
+ /*FALLTHROUGH*/
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( yywrap( ) )
+ return EOF;
+
+ if ( ! (yy_did_buffer_switch_on_eof) )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput();
+#else
+ return input();
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ (yy_c_buf_p) = (yytext_ptr) + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */
+ *(yy_c_buf_p) = '\0'; /* preserve yytext */
+ (yy_hold_char) = *++(yy_c_buf_p);
+
+ if ( c == '\n' )
+
+ yylineno++;
+;
+
+ return c;
+}
+#endif /* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ *
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+ void yyrestart (FILE * input_file )
+{
+
+ if ( ! YY_CURRENT_BUFFER ){
+ yyensure_buffer_stack ();
+ YY_CURRENT_BUFFER_LVALUE =
+ yy_create_buffer(yyin,YY_BUF_SIZE );
+ }
+
+ yy_init_buffer(YY_CURRENT_BUFFER,input_file );
+ yy_load_buffer_state( );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ *
+ */
+ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer )
+{
+
+ /* TODO. We should be able to replace this entire function body
+ * with
+ * yypop_buffer_state();
+ * yypush_buffer_state(new_buffer);
+ */
+ yyensure_buffer_stack ();
+ if ( YY_CURRENT_BUFFER == new_buffer )
+ return;
+
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *(yy_c_buf_p) = (yy_hold_char);
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+ yy_load_buffer_state( );
+
+ /* We don't actually know whether we did this switch during
+ * EOF (yywrap()) processing, but the only time this flag
+ * is looked at is after yywrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ (yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void yy_load_buffer_state (void)
+{
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+ yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+ (yy_hold_char) = *(yy_c_buf_p);
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ *
+ * @return the allocated buffer state.
+ */
+ YY_BUFFER_STATE yy_create_buffer (FILE * file, int size )
+{
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_buf_size = (yy_size_t)size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ yy_init_buffer(b,file );
+
+ return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with yy_create_buffer()
+ *
+ */
+ void yy_delete_buffer (YY_BUFFER_STATE b )
+{
+
+ if ( ! b )
+ return;
+
+ if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ yyfree((void *) b->yy_ch_buf );
+
+ yyfree((void *) b );
+}
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a yyrestart() or at EOF.
+ */
+ static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file )
+
+{
+ int oerrno = errno;
+
+ yy_flush_buffer(b );
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+ /* If b is the current buffer, then yy_init_buffer was _probably_
+ * called from yyrestart() or through yy_get_next_buffer.
+ * In that case, we don't want to reset the lineno or column.
+ */
+ if (b != YY_CURRENT_BUFFER){
+ b->yy_bs_lineno = 1;
+ b->yy_bs_column = 0;
+ }
+
+ b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+
+ errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ *
+ */
+ void yy_flush_buffer (YY_BUFFER_STATE b )
+{
+ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == YY_CURRENT_BUFFER )
+ yy_load_buffer_state( );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ * the current state. This function will allocate the stack
+ * if necessary.
+ * @param new_buffer The new state.
+ *
+ */
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+ if (new_buffer == NULL)
+ return;
+
+ yyensure_buffer_stack();
+
+ /* This block is copied from yy_switch_to_buffer. */
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *(yy_c_buf_p) = (yy_hold_char);
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ /* Only push if top exists. Otherwise, replace top. */
+ if (YY_CURRENT_BUFFER)
+ (yy_buffer_stack_top)++;
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+ /* copied from yy_switch_to_buffer. */
+ yy_load_buffer_state( );
+ (yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ * The next element becomes the new top.
+ *
+ */
+void yypop_buffer_state (void)
+{
+ if (!YY_CURRENT_BUFFER)
+ return;
+
+ yy_delete_buffer(YY_CURRENT_BUFFER );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ if ((yy_buffer_stack_top) > 0)
+ --(yy_buffer_stack_top);
+
+ if (YY_CURRENT_BUFFER) {
+ yy_load_buffer_state( );
+ (yy_did_buffer_switch_on_eof) = 1;
+ }
+}
+
+/* Allocates the stack if it does not exist.
+ * Guarantees space for at least one push.
+ */
+static void yyensure_buffer_stack (void)
+{
+ yy_size_t num_to_alloc;
+
+ if (!(yy_buffer_stack)) {
+
+ /* First allocation is just for 2 elements, since we don't know if this
+ * scanner will even need a stack. We use 2 instead of 1 to avoid an
+ * immediate realloc on the next call.
+ */
+ num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */
+ (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
+ (num_to_alloc * sizeof(struct yy_buffer_state*)
+ );
+ if ( ! (yy_buffer_stack) )
+ YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+ memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+
+ (yy_buffer_stack_max) = num_to_alloc;
+ (yy_buffer_stack_top) = 0;
+ return;
+ }
+
+ if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+ /* Increase the buffer to prepare for a possible push. */
+ yy_size_t grow_size = 8 /* arbitrary grow size */;
+
+ num_to_alloc = (yy_buffer_stack_max) + grow_size;
+ (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
+ ((yy_buffer_stack),
+ num_to_alloc * sizeof(struct yy_buffer_state*)
+ );
+ if ( ! (yy_buffer_stack) )
+ YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+ /* zero only the new slots.*/
+ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+ (yy_buffer_stack_max) = num_to_alloc;
+ }
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ *
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size )
+{
+ YY_BUFFER_STATE b;
+
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return 0;
+
+ b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+ b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = 0;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ yy_switch_to_buffer(b );
+
+ return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to yylex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ *
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ * yy_scan_bytes() instead.
+ */
+YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
+{
+
+ return yy_scan_bytes(yystr,strlen(yystr) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
+ * scan from a @e copy of @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
+ *
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len )
+{
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ yy_size_t i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = _yybytes_len + 2;
+ buf = (char *) yyalloc(n );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+ for ( i = 0; i < _yybytes_len; ++i )
+ buf[i] = yybytes[i];
+
+ buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+ b = yy_scan_buffer(buf,n );
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg )
+{
+ (void) fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ yytext[yyleng] = (yy_hold_char); \
+ (yy_c_buf_p) = yytext + yyless_macro_arg; \
+ (yy_hold_char) = *(yy_c_buf_p); \
+ *(yy_c_buf_p) = '\0'; \
+ yyleng = yyless_macro_arg; \
+ } \
+ while ( 0 )
+
+/* Accessor methods (get/set functions) to struct members. */
+
+/** Get the current line number.
+ *
+ */
+int yyget_lineno (void)
+{
+
+ return yylineno;
+}
+
+/** Get the input stream.
+ *
+ */
+FILE *yyget_in (void)
+{
+ return yyin;
+}
+
+/** Get the output stream.
+ *
+ */
+FILE *yyget_out (void)
+{
+ return yyout;
+}
+
+/** Get the length of the current token.
+ *
+ */
+yy_size_t yyget_leng (void)
+{
+ return yyleng;
+}
+
+/** Get the current token.
+ *
+ */
+
+char *yyget_text (void)
+{
+ return yytext;
+}
+
+/** Set the current line number.
+ * @param _line_number line number
+ *
+ */
+void yyset_lineno (int _line_number )
+{
+
+ yylineno = _line_number;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param _in_str A readable stream.
+ *
+ * @see yy_switch_to_buffer
+ */
+void yyset_in (FILE * _in_str )
+{
+ yyin = _in_str ;
+}
+
+void yyset_out (FILE * _out_str )
+{
+ yyout = _out_str ;
+}
+
+int yyget_debug (void)
+{
+ return yy_flex_debug;
+}
+
+void yyset_debug (int _bdebug )
+{
+ yy_flex_debug = _bdebug ;
+}
+
+static int yy_init_globals (void)
+{
+ /* Initialization is the same as for the non-reentrant scanner.
+ * This function is called from yylex_destroy(), so don't allocate here.
+ */
+
+ /* We do not touch yylineno unless the option is enabled. */
+ yylineno = 1;
+
+ (yy_buffer_stack) = 0;
+ (yy_buffer_stack_top) = 0;
+ (yy_buffer_stack_max) = 0;
+ (yy_c_buf_p) = (char *) 0;
+ (yy_init) = 0;
+ (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+ yyin = stdin;
+ yyout = stdout;
+#else
+ yyin = (FILE *) 0;
+ yyout = (FILE *) 0;
+#endif
+
+ /* For future reference: Set errno on error, since we are called by
+ * yylex_init()
+ */
+ return 0;
+}
+
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy (void)
+{
+
+ /* Pop the buffer stack, destroying each element. */
+ while(YY_CURRENT_BUFFER){
+ yy_delete_buffer(YY_CURRENT_BUFFER );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ yypop_buffer_state();
+ }
+
+ /* Destroy the stack itself. */
+ yyfree((yy_buffer_stack) );
+ (yy_buffer_stack) = NULL;
+
+ /* Reset the globals. This is important in a non-reentrant scanner so the next time
+ * yylex() is called, initialization will occur. */
+ yy_init_globals( );
+
+ return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
+
+ int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s )
+{
+ int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+}
+#endif
+
+void *yyalloc (yy_size_t size )
+{
+ return (void *) malloc( size );
+}
+
+void *yyrealloc (void * ptr, yy_size_t size )
+{
+
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return (void *) realloc( (char *) ptr, size );
+}
+
+void yyfree (void * ptr )
+{
+ free( (char *) ptr ); /* see yyrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 164 "parser/tf_fuzz_grammar.l"
+
+
+
+
diff --git a/tf_fuzz/parser/tf_fuzz_grammar.lex.o b/tf_fuzz/parser/tf_fuzz_grammar.lex.o
new file mode 100644
index 0000000..bba09f8
--- /dev/null
+++ b/tf_fuzz/parser/tf_fuzz_grammar.lex.o
Binary files differ
diff --git a/tf_fuzz/parser/tf_fuzz_grammar.output b/tf_fuzz/parser/tf_fuzz_grammar.output
new file mode 100644
index 0000000..aaadb77
--- /dev/null
+++ b/tf_fuzz/parser/tf_fuzz_grammar.output
@@ -0,0 +1,2471 @@
+Terminals unused in grammar
+
+ RAW_TEXT
+ EQUAL
+ ERROR
+
+
+Grammar
+
+ 0 $accept: lines $end
+
+ 1 lines: %empty
+ 2 | line lines
+
+ 3 line: PURPOSE
+ 4 | block
+ 5 | command SEMICOLON
+ 6 | command expect SEMICOLON
+
+ 7 command: set_command
+ 8 | remove_command
+ 9 | read_command
+ 10 | secure_command
+ 11 | done_command
+
+ 12 expect: EXPECT PASS
+ 13 | EXPECT FAIL
+ 14 | EXPECT NOTHING
+ 15 | EXPECT IDENTIFIER
+
+ 16 set_command: SET SST sst_set_base_args sst_set_extended_args
+ 17 | SET KEY key_set_args
+ 18 | SET POLICY policy_set_args
+
+ 19 read_command: READ SST sst_read_args
+ 20 | READ KEY key_read_args
+ 21 | READ POLICY policy_read_args
+
+ 22 remove_command: REMOVE SST sst_remove_args
+ 23 | REMOVE KEY key_remove_args
+
+ 24 secure_command: SECURE HASH NEQ ASSET_IDENTIFIER_LIST
+
+ 25 done_command: DONE
+
+ 26 literal_or_random_data: DATA LITERAL
+ 27 | DATA STAR
+
+ 28 sst_set_base_args: sst_asset_name literal_or_random_data
+ 29 | sst_asset_name
+ 30 | sst_asset_name VAR IDENTIFIER
+ 31 | sst_asset_name DFNAME sst_asset_set_file_path
+
+ 32 sst_set_extended_args: %empty
+ 33 | FLAG sst_flags
+
+ 34 sst_flags: %empty
+ 35 | sst_flag sst_flags
+
+ 36 sst_flag: none
+ 37 | write_once
+ 38 | no_rp
+ 39 | no_conf
+
+ 40 none: NONE
+
+ 41 write_once: WRITE_ONCE
+
+ 42 no_rp: NO_RP
+
+ 43 no_conf: NO_CONF
+
+ 44 sst_offset_spec: NUMBER_TOK
+
+ 45 sst_read_args: sst_asset_name read_args sst_read_extended_args
+
+ 46 read_args: VAR IDENTIFIER
+ 47 | CHECK read_args_var_name
+ 48 | CHECK LITERAL
+ 49 | PRINT
+ 50 | HASH
+ 51 | DFNAME sst_asset_dump_file_path
+
+ 52 sst_read_extended_args: %empty
+ 53 | OFFSET sst_offset_spec
+
+ 54 sst_remove_args: sst_asset_name
+ 55 | random_picked_asset
+
+ 56 asset_designator: NAME ASSET_IDENTIFIER_LIST
+ 57 | NAME STAR
+
+ 58 single_existing_asset: IDENTIFIER
+ 59 | random_picked_asset
+
+ 60 random_picked_asset: STAR ACTIVE
+ 61 | STAR DELETED
+
+ 62 sst_asset_name: asset_designator
+ 63 | UID ASSET_NUMBER_LIST
+ 64 | UID STAR
+
+ 65 sst_asset_set_file_path: FILE_PATH
+
+ 66 read_args_var_name: IDENTIFIER
+
+ 67 sst_asset_dump_file_path: FILE_PATH
+
+ 68 key_size: NUMBER_TOK
+
+ 69 policy_usage_list: ATTR policy_usage policy_usages
+
+ 70 policy_usages: %empty
+ 71 | policy_usage policy_usages
+
+ 72 export: EXPORT
+
+ 73 noexport: NOEXPORT
+
+ 74 copy: COPY
+
+ 75 nocopy: NOCOPY
+
+ 76 encrypt: ENCRYPT
+
+ 77 noencrypt: NOENCRYPT
+
+ 78 decrypt: DECRYPT
+
+ 79 nodecrypt: NODECRYPT
+
+ 80 sign: SIGN
+
+ 81 nosign: NOSIGN
+
+ 82 verify: VERIFY
+
+ 83 noverify: NOVERIFY
+
+ 84 derive: DERIVE
+
+ 85 noderive: NODERIVE
+
+ 86 persistent: PERSISTENT
+
+ 87 volatle: VOLATILE
+
+ 88 policy_usage: export
+ 89 | copy
+ 90 | encrypt
+ 91 | decrypt
+ 92 | sign
+ 93 | verify
+ 94 | derive
+ 95 | noexport
+ 96 | nocopy
+ 97 | noencrypt
+ 98 | nodecrypt
+ 99 | nosign
+ 100 | noverify
+ 101 | noderive
+ 102 | persistent
+ 103 | volatle
+ 104 | key_size
+
+ 105 policy_type: TYPE IDENTIFIER
+
+ 106 policy_algorithm: ALG IDENTIFIER
+
+ 107 policy_specs: %empty
+ 108 | policy_spec policy_specs
+
+ 109 policy_spec: policy_usage_list
+ 110 | policy_type
+ 111 | policy_algorithm
+
+ 112 policy_asset_spec: %empty
+ 113 | NAME ASSET_IDENTIFIER_LIST
+ 114 | NAME STAR
+
+ 115 policy_asset_name: NAME IDENTIFIER
+ 116 | STAR ACTIVE
+ 117 | STAR DELETED
+ 118 | KEY IDENTIFIER
+
+ 119 policy_set_args: policy_asset_spec policy_specs
+
+ 120 policy_read_args: policy_asset_name read_args
+
+ 121 key_set_sources: %empty
+ 122 | key_set_source key_set_sources
+
+ 123 key_set_source: literal_or_random_data
+ 124 | POLICY IDENTIFIER
+
+ 125 key_data_or_not: %empty
+ 126 | literal_or_random_data
+
+ 127 key_set_args: asset_designator key_set_sources
+ 128 | asset_designator FROM single_existing_asset POLICY IDENTIFIER
+ 129 | asset_designator key_data_or_not WITH policy_specs
+
+ 130 key_remove_args: asset_designator
+
+ 131 key_read_args: asset_designator read_args
+
+ 132 block: SHUFFLE block_content
+ 133 | exact_sel_count OF block_content
+ 134 | low_sel_count TO high_sel_count OF block_content
+
+ 135 block_content: open_brace lines close_brace
+ 136 | line
+
+ 137 open_brace: OPEN_BRACE
+
+ 138 close_brace: CLOSE_BRACE
+
+ 139 ASSET_NUMBER_LIST: ASSET_NUMBER ASSET_NUMBERS
+
+ 140 ASSET_NUMBERS: %empty
+ 141 | ASSET_NUMBER ASSET_NUMBERS
+
+ 142 ASSET_NUMBER: NUMBER_TOK
+
+ 143 ASSET_IDENTIFIER_LIST: ASSET_IDENTIFIER ASSET_IDENTIFIERS
+
+ 144 ASSET_IDENTIFIERS: %empty
+ 145 | ASSET_IDENTIFIER ASSET_IDENTIFIERS
+
+ 146 ASSET_IDENTIFIER: IDENTIFIER_TOK
+
+ 147 IDENTIFIER: IDENTIFIER_TOK
+
+ 148 FILE_PATH: FILE_PATH_TOK
+
+ 149 exact_sel_count: NUMBER
+
+ 150 low_sel_count: NUMBER
+
+ 151 high_sel_count: NUMBER
+
+ 152 NUMBER: NUMBER_TOK
+
+ 153 LITERAL: LITERAL_TOK
+ 154 | HEX_LIST
+
+
+Terminals, with rules where they appear
+
+$end (0) 0
+error (256)
+PURPOSE (258) 3
+RAW_TEXT (259)
+SET (260) 16 17 18
+READ (261) 19 20 21
+REMOVE (262) 22 23
+SECURE (263) 24
+DONE (264) 25
+SST (265) 16 19 22
+KEY (266) 17 20 23 118
+POLICY (267) 18 21 124 128
+NAME (268) 56 57 113 114 115
+UID (269) 63 64
+STAR (270) 27 57 60 61 64 114 116 117
+ACTIVE (271) 60 116
+DELETED (272) 61 117
+EQUAL (273)
+DATA (274) 26 27
+DFNAME (275) 31 51
+FLAG (276) 33
+NONE (277) 40
+WRITE_ONCE (278) 41
+NO_RP (279) 42
+NO_CONF (280) 43
+OFFSET (281) 53
+CHECK (282) 47 48
+VAR (283) 30 46
+HASH (284) 24 50
+NEQ (285) 24
+PRINT (286) 49
+EXPECT (287) 12 13 14 15
+PASS (288) 12
+FAIL (289) 13
+NOTHING (290) 14
+ERROR (291)
+IDENTIFIER_TOK (292) 146 147
+LITERAL_TOK (293) 153
+HEX_LIST (294) 154
+FILE_PATH_TOK (295) 148
+NUMBER_TOK (296) 44 68 142 152
+SEMICOLON (297) 5 6
+SHUFFLE (298) 132
+TO (299) 134
+OF (300) 133 134
+OPEN_BRACE (301) 137
+CLOSE_BRACE (302) 138
+ATTR (303) 69
+TYPE (304) 105
+ALG (305) 106
+EXPORT (306) 72
+COPY (307) 74
+ENCRYPT (308) 76
+DECRYPT (309) 78
+SIGN (310) 80
+VERIFY (311) 82
+DERIVE (312) 84
+NOEXPORT (313) 73
+NOCOPY (314) 75
+NOENCRYPT (315) 77
+NODECRYPT (316) 79
+NOSIGN (317) 81
+NOVERIFY (318) 83
+NODERIVE (319) 85
+PERSISTENT (320) 86
+VOLATILE (321) 87
+FROM (322) 128
+WITH (323) 129
+
+
+Nonterminals, with rules where they appear
+
+$accept (69)
+ on left: 0
+lines (70)
+ on left: 1 2, on right: 0 2 135
+line (71)
+ on left: 3 4 5 6, on right: 2 136
+command (72)
+ on left: 7 8 9 10 11, on right: 5 6
+expect (73)
+ on left: 12 13 14 15, on right: 6
+set_command (74)
+ on left: 16 17 18, on right: 7
+read_command (75)
+ on left: 19 20 21, on right: 9
+remove_command (76)
+ on left: 22 23, on right: 8
+secure_command (77)
+ on left: 24, on right: 10
+done_command (78)
+ on left: 25, on right: 11
+literal_or_random_data (79)
+ on left: 26 27, on right: 28 123 126
+sst_set_base_args (80)
+ on left: 28 29 30 31, on right: 16
+sst_set_extended_args (81)
+ on left: 32 33, on right: 16
+sst_flags (82)
+ on left: 34 35, on right: 33 35
+sst_flag (83)
+ on left: 36 37 38 39, on right: 35
+none (84)
+ on left: 40, on right: 36
+write_once (85)
+ on left: 41, on right: 37
+no_rp (86)
+ on left: 42, on right: 38
+no_conf (87)
+ on left: 43, on right: 39
+sst_offset_spec (88)
+ on left: 44, on right: 53
+sst_read_args (89)
+ on left: 45, on right: 19
+read_args (90)
+ on left: 46 47 48 49 50 51, on right: 45 120 131
+sst_read_extended_args (91)
+ on left: 52 53, on right: 45
+sst_remove_args (92)
+ on left: 54 55, on right: 22
+asset_designator (93)
+ on left: 56 57, on right: 62 127 128 129 130 131
+single_existing_asset (94)
+ on left: 58 59, on right: 128
+random_picked_asset (95)
+ on left: 60 61, on right: 55 59
+sst_asset_name (96)
+ on left: 62 63 64, on right: 28 29 30 31 45 54
+sst_asset_set_file_path (97)
+ on left: 65, on right: 31
+read_args_var_name (98)
+ on left: 66, on right: 47
+sst_asset_dump_file_path (99)
+ on left: 67, on right: 51
+key_size (100)
+ on left: 68, on right: 104
+policy_usage_list (101)
+ on left: 69, on right: 109
+policy_usages (102)
+ on left: 70 71, on right: 69 71
+export (103)
+ on left: 72, on right: 88
+noexport (104)
+ on left: 73, on right: 95
+copy (105)
+ on left: 74, on right: 89
+nocopy (106)
+ on left: 75, on right: 96
+encrypt (107)
+ on left: 76, on right: 90
+noencrypt (108)
+ on left: 77, on right: 97
+decrypt (109)
+ on left: 78, on right: 91
+nodecrypt (110)
+ on left: 79, on right: 98
+sign (111)
+ on left: 80, on right: 92
+nosign (112)
+ on left: 81, on right: 99
+verify (113)
+ on left: 82, on right: 93
+noverify (114)
+ on left: 83, on right: 100
+derive (115)
+ on left: 84, on right: 94
+noderive (116)
+ on left: 85, on right: 101
+persistent (117)
+ on left: 86, on right: 102
+volatle (118)
+ on left: 87, on right: 103
+policy_usage (119)
+ on left: 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104,
+ on right: 69 71
+policy_type (120)
+ on left: 105, on right: 110
+policy_algorithm (121)
+ on left: 106, on right: 111
+policy_specs (122)
+ on left: 107 108, on right: 108 119 129
+policy_spec (123)
+ on left: 109 110 111, on right: 108
+policy_asset_spec (124)
+ on left: 112 113 114, on right: 119
+policy_asset_name (125)
+ on left: 115 116 117 118, on right: 120
+policy_set_args (126)
+ on left: 119, on right: 18
+policy_read_args (127)
+ on left: 120, on right: 21
+key_set_sources (128)
+ on left: 121 122, on right: 122 127
+key_set_source (129)
+ on left: 123 124, on right: 122
+key_data_or_not (130)
+ on left: 125 126, on right: 129
+key_set_args (131)
+ on left: 127 128 129, on right: 17
+key_remove_args (132)
+ on left: 130, on right: 23
+key_read_args (133)
+ on left: 131, on right: 20
+block (134)
+ on left: 132 133 134, on right: 4
+block_content (135)
+ on left: 135 136, on right: 132 133 134
+open_brace (136)
+ on left: 137, on right: 135
+close_brace (137)
+ on left: 138, on right: 135
+ASSET_NUMBER_LIST (138)
+ on left: 139, on right: 63
+ASSET_NUMBERS (139)
+ on left: 140 141, on right: 139 141
+ASSET_NUMBER (140)
+ on left: 142, on right: 139 141
+ASSET_IDENTIFIER_LIST (141)
+ on left: 143, on right: 24 56 113
+ASSET_IDENTIFIERS (142)
+ on left: 144 145, on right: 143 145
+ASSET_IDENTIFIER (143)
+ on left: 146, on right: 143 145
+IDENTIFIER (144)
+ on left: 147, on right: 15 30 46 58 66 105 106 115 118 124 128
+FILE_PATH (145)
+ on left: 148, on right: 65 67
+exact_sel_count (146)
+ on left: 149, on right: 133
+low_sel_count (147)
+ on left: 150, on right: 134
+high_sel_count (148)
+ on left: 151, on right: 134
+NUMBER (149)
+ on left: 152, on right: 149 150 151
+LITERAL (150)
+ on left: 153 154, on right: 26 48
+
+
+State 0
+
+ 0 $accept: . lines $end
+
+ PURPOSE shift, and go to state 1
+ SET shift, and go to state 2
+ READ shift, and go to state 3
+ REMOVE shift, and go to state 4
+ SECURE shift, and go to state 5
+ DONE shift, and go to state 6
+ NUMBER_TOK shift, and go to state 7
+ SHUFFLE shift, and go to state 8
+
+ $default reduce using rule 1 (lines)
+
+ lines go to state 9
+ line go to state 10
+ command go to state 11
+ set_command go to state 12
+ read_command go to state 13
+ remove_command go to state 14
+ secure_command go to state 15
+ done_command go to state 16
+ block go to state 17
+ exact_sel_count go to state 18
+ low_sel_count go to state 19
+ NUMBER go to state 20
+
+
+State 1
+
+ 3 line: PURPOSE .
+
+ $default reduce using rule 3 (line)
+
+
+State 2
+
+ 16 set_command: SET . SST sst_set_base_args sst_set_extended_args
+ 17 | SET . KEY key_set_args
+ 18 | SET . POLICY policy_set_args
+
+ SST shift, and go to state 21
+ KEY shift, and go to state 22
+ POLICY shift, and go to state 23
+
+
+State 3
+
+ 19 read_command: READ . SST sst_read_args
+ 20 | READ . KEY key_read_args
+ 21 | READ . POLICY policy_read_args
+
+ SST shift, and go to state 24
+ KEY shift, and go to state 25
+ POLICY shift, and go to state 26
+
+
+State 4
+
+ 22 remove_command: REMOVE . SST sst_remove_args
+ 23 | REMOVE . KEY key_remove_args
+
+ SST shift, and go to state 27
+ KEY shift, and go to state 28
+
+
+State 5
+
+ 24 secure_command: SECURE . HASH NEQ ASSET_IDENTIFIER_LIST
+
+ HASH shift, and go to state 29
+
+
+State 6
+
+ 25 done_command: DONE .
+
+ $default reduce using rule 25 (done_command)
+
+
+State 7
+
+ 152 NUMBER: NUMBER_TOK .
+
+ $default reduce using rule 152 (NUMBER)
+
+
+State 8
+
+ 132 block: SHUFFLE . block_content
+
+ PURPOSE shift, and go to state 1
+ SET shift, and go to state 2
+ READ shift, and go to state 3
+ REMOVE shift, and go to state 4
+ SECURE shift, and go to state 5
+ DONE shift, and go to state 6
+ NUMBER_TOK shift, and go to state 7
+ SHUFFLE shift, and go to state 8
+ OPEN_BRACE shift, and go to state 30
+
+ line go to state 31
+ command go to state 11
+ set_command go to state 12
+ read_command go to state 13
+ remove_command go to state 14
+ secure_command go to state 15
+ done_command go to state 16
+ block go to state 17
+ block_content go to state 32
+ open_brace go to state 33
+ exact_sel_count go to state 18
+ low_sel_count go to state 19
+ NUMBER go to state 20
+
+
+State 9
+
+ 0 $accept: lines . $end
+
+ $end shift, and go to state 34
+
+
+State 10
+
+ 2 lines: line . lines
+
+ PURPOSE shift, and go to state 1
+ SET shift, and go to state 2
+ READ shift, and go to state 3
+ REMOVE shift, and go to state 4
+ SECURE shift, and go to state 5
+ DONE shift, and go to state 6
+ NUMBER_TOK shift, and go to state 7
+ SHUFFLE shift, and go to state 8
+
+ $default reduce using rule 1 (lines)
+
+ lines go to state 35
+ line go to state 10
+ command go to state 11
+ set_command go to state 12
+ read_command go to state 13
+ remove_command go to state 14
+ secure_command go to state 15
+ done_command go to state 16
+ block go to state 17
+ exact_sel_count go to state 18
+ low_sel_count go to state 19
+ NUMBER go to state 20
+
+
+State 11
+
+ 5 line: command . SEMICOLON
+ 6 | command . expect SEMICOLON
+
+ EXPECT shift, and go to state 36
+ SEMICOLON shift, and go to state 37
+
+ expect go to state 38
+
+
+State 12
+
+ 7 command: set_command .
+
+ $default reduce using rule 7 (command)
+
+
+State 13
+
+ 9 command: read_command .
+
+ $default reduce using rule 9 (command)
+
+
+State 14
+
+ 8 command: remove_command .
+
+ $default reduce using rule 8 (command)
+
+
+State 15
+
+ 10 command: secure_command .
+
+ $default reduce using rule 10 (command)
+
+
+State 16
+
+ 11 command: done_command .
+
+ $default reduce using rule 11 (command)
+
+
+State 17
+
+ 4 line: block .
+
+ $default reduce using rule 4 (line)
+
+
+State 18
+
+ 133 block: exact_sel_count . OF block_content
+
+ OF shift, and go to state 39
+
+
+State 19
+
+ 134 block: low_sel_count . TO high_sel_count OF block_content
+
+ TO shift, and go to state 40
+
+
+State 20
+
+ 149 exact_sel_count: NUMBER .
+ 150 low_sel_count: NUMBER .
+
+ TO reduce using rule 150 (low_sel_count)
+ $default reduce using rule 149 (exact_sel_count)
+
+
+State 21
+
+ 16 set_command: SET SST . sst_set_base_args sst_set_extended_args
+
+ NAME shift, and go to state 41
+ UID shift, and go to state 42
+
+ sst_set_base_args go to state 43
+ asset_designator go to state 44
+ sst_asset_name go to state 45
+
+
+State 22
+
+ 17 set_command: SET KEY . key_set_args
+
+ NAME shift, and go to state 41
+
+ asset_designator go to state 46
+ key_set_args go to state 47
+
+
+State 23
+
+ 18 set_command: SET POLICY . policy_set_args
+
+ NAME shift, and go to state 48
+
+ $default reduce using rule 112 (policy_asset_spec)
+
+ policy_asset_spec go to state 49
+ policy_set_args go to state 50
+
+
+State 24
+
+ 19 read_command: READ SST . sst_read_args
+
+ NAME shift, and go to state 41
+ UID shift, and go to state 42
+
+ sst_read_args go to state 51
+ asset_designator go to state 44
+ sst_asset_name go to state 52
+
+
+State 25
+
+ 20 read_command: READ KEY . key_read_args
+
+ NAME shift, and go to state 41
+
+ asset_designator go to state 53
+ key_read_args go to state 54
+
+
+State 26
+
+ 21 read_command: READ POLICY . policy_read_args
+
+ KEY shift, and go to state 55
+ NAME shift, and go to state 56
+ STAR shift, and go to state 57
+
+ policy_asset_name go to state 58
+ policy_read_args go to state 59
+
+
+State 27
+
+ 22 remove_command: REMOVE SST . sst_remove_args
+
+ NAME shift, and go to state 41
+ UID shift, and go to state 42
+ STAR shift, and go to state 60
+
+ sst_remove_args go to state 61
+ asset_designator go to state 44
+ random_picked_asset go to state 62
+ sst_asset_name go to state 63
+
+
+State 28
+
+ 23 remove_command: REMOVE KEY . key_remove_args
+
+ NAME shift, and go to state 41
+
+ asset_designator go to state 64
+ key_remove_args go to state 65
+
+
+State 29
+
+ 24 secure_command: SECURE HASH . NEQ ASSET_IDENTIFIER_LIST
+
+ NEQ shift, and go to state 66
+
+
+State 30
+
+ 137 open_brace: OPEN_BRACE .
+
+ $default reduce using rule 137 (open_brace)
+
+
+State 31
+
+ 136 block_content: line .
+
+ $default reduce using rule 136 (block_content)
+
+
+State 32
+
+ 132 block: SHUFFLE block_content .
+
+ $default reduce using rule 132 (block)
+
+
+State 33
+
+ 135 block_content: open_brace . lines close_brace
+
+ PURPOSE shift, and go to state 1
+ SET shift, and go to state 2
+ READ shift, and go to state 3
+ REMOVE shift, and go to state 4
+ SECURE shift, and go to state 5
+ DONE shift, and go to state 6
+ NUMBER_TOK shift, and go to state 7
+ SHUFFLE shift, and go to state 8
+
+ $default reduce using rule 1 (lines)
+
+ lines go to state 67
+ line go to state 10
+ command go to state 11
+ set_command go to state 12
+ read_command go to state 13
+ remove_command go to state 14
+ secure_command go to state 15
+ done_command go to state 16
+ block go to state 17
+ exact_sel_count go to state 18
+ low_sel_count go to state 19
+ NUMBER go to state 20
+
+
+State 34
+
+ 0 $accept: lines $end .
+
+ $default accept
+
+
+State 35
+
+ 2 lines: line lines .
+
+ $default reduce using rule 2 (lines)
+
+
+State 36
+
+ 12 expect: EXPECT . PASS
+ 13 | EXPECT . FAIL
+ 14 | EXPECT . NOTHING
+ 15 | EXPECT . IDENTIFIER
+
+ PASS shift, and go to state 68
+ FAIL shift, and go to state 69
+ NOTHING shift, and go to state 70
+ IDENTIFIER_TOK shift, and go to state 71
+
+ IDENTIFIER go to state 72
+
+
+State 37
+
+ 5 line: command SEMICOLON .
+
+ $default reduce using rule 5 (line)
+
+
+State 38
+
+ 6 line: command expect . SEMICOLON
+
+ SEMICOLON shift, and go to state 73
+
+
+State 39
+
+ 133 block: exact_sel_count OF . block_content
+
+ PURPOSE shift, and go to state 1
+ SET shift, and go to state 2
+ READ shift, and go to state 3
+ REMOVE shift, and go to state 4
+ SECURE shift, and go to state 5
+ DONE shift, and go to state 6
+ NUMBER_TOK shift, and go to state 7
+ SHUFFLE shift, and go to state 8
+ OPEN_BRACE shift, and go to state 30
+
+ line go to state 31
+ command go to state 11
+ set_command go to state 12
+ read_command go to state 13
+ remove_command go to state 14
+ secure_command go to state 15
+ done_command go to state 16
+ block go to state 17
+ block_content go to state 74
+ open_brace go to state 33
+ exact_sel_count go to state 18
+ low_sel_count go to state 19
+ NUMBER go to state 20
+
+
+State 40
+
+ 134 block: low_sel_count TO . high_sel_count OF block_content
+
+ NUMBER_TOK shift, and go to state 7
+
+ high_sel_count go to state 75
+ NUMBER go to state 76
+
+
+State 41
+
+ 56 asset_designator: NAME . ASSET_IDENTIFIER_LIST
+ 57 | NAME . STAR
+
+ STAR shift, and go to state 77
+ IDENTIFIER_TOK shift, and go to state 78
+
+ ASSET_IDENTIFIER_LIST go to state 79
+ ASSET_IDENTIFIER go to state 80
+
+
+State 42
+
+ 63 sst_asset_name: UID . ASSET_NUMBER_LIST
+ 64 | UID . STAR
+
+ STAR shift, and go to state 81
+ NUMBER_TOK shift, and go to state 82
+
+ ASSET_NUMBER_LIST go to state 83
+ ASSET_NUMBER go to state 84
+
+
+State 43
+
+ 16 set_command: SET SST sst_set_base_args . sst_set_extended_args
+
+ FLAG shift, and go to state 85
+
+ $default reduce using rule 32 (sst_set_extended_args)
+
+ sst_set_extended_args go to state 86
+
+
+State 44
+
+ 62 sst_asset_name: asset_designator .
+
+ $default reduce using rule 62 (sst_asset_name)
+
+
+State 45
+
+ 28 sst_set_base_args: sst_asset_name . literal_or_random_data
+ 29 | sst_asset_name .
+ 30 | sst_asset_name . VAR IDENTIFIER
+ 31 | sst_asset_name . DFNAME sst_asset_set_file_path
+
+ DATA shift, and go to state 87
+ DFNAME shift, and go to state 88
+ VAR shift, and go to state 89
+
+ $default reduce using rule 29 (sst_set_base_args)
+
+ literal_or_random_data go to state 90
+
+
+State 46
+
+ 127 key_set_args: asset_designator . key_set_sources
+ 128 | asset_designator . FROM single_existing_asset POLICY IDENTIFIER
+ 129 | asset_designator . key_data_or_not WITH policy_specs
+
+ POLICY shift, and go to state 91
+ DATA shift, and go to state 87
+ FROM shift, and go to state 92
+
+ WITH reduce using rule 125 (key_data_or_not)
+ $default reduce using rule 121 (key_set_sources)
+
+ literal_or_random_data go to state 93
+ key_set_sources go to state 94
+ key_set_source go to state 95
+ key_data_or_not go to state 96
+
+
+State 47
+
+ 17 set_command: SET KEY key_set_args .
+
+ $default reduce using rule 17 (set_command)
+
+
+State 48
+
+ 113 policy_asset_spec: NAME . ASSET_IDENTIFIER_LIST
+ 114 | NAME . STAR
+
+ STAR shift, and go to state 97
+ IDENTIFIER_TOK shift, and go to state 78
+
+ ASSET_IDENTIFIER_LIST go to state 98
+ ASSET_IDENTIFIER go to state 80
+
+
+State 49
+
+ 119 policy_set_args: policy_asset_spec . policy_specs
+
+ ATTR shift, and go to state 99
+ TYPE shift, and go to state 100
+ ALG shift, and go to state 101
+
+ $default reduce using rule 107 (policy_specs)
+
+ policy_usage_list go to state 102
+ policy_type go to state 103
+ policy_algorithm go to state 104
+ policy_specs go to state 105
+ policy_spec go to state 106
+
+
+State 50
+
+ 18 set_command: SET POLICY policy_set_args .
+
+ $default reduce using rule 18 (set_command)
+
+
+State 51
+
+ 19 read_command: READ SST sst_read_args .
+
+ $default reduce using rule 19 (read_command)
+
+
+State 52
+
+ 45 sst_read_args: sst_asset_name . read_args sst_read_extended_args
+
+ DFNAME shift, and go to state 107
+ CHECK shift, and go to state 108
+ VAR shift, and go to state 109
+ HASH shift, and go to state 110
+ PRINT shift, and go to state 111
+
+ read_args go to state 112
+
+
+State 53
+
+ 131 key_read_args: asset_designator . read_args
+
+ DFNAME shift, and go to state 107
+ CHECK shift, and go to state 108
+ VAR shift, and go to state 109
+ HASH shift, and go to state 110
+ PRINT shift, and go to state 111
+
+ read_args go to state 113
+
+
+State 54
+
+ 20 read_command: READ KEY key_read_args .
+
+ $default reduce using rule 20 (read_command)
+
+
+State 55
+
+ 118 policy_asset_name: KEY . IDENTIFIER
+
+ IDENTIFIER_TOK shift, and go to state 71
+
+ IDENTIFIER go to state 114
+
+
+State 56
+
+ 115 policy_asset_name: NAME . IDENTIFIER
+
+ IDENTIFIER_TOK shift, and go to state 71
+
+ IDENTIFIER go to state 115
+
+
+State 57
+
+ 116 policy_asset_name: STAR . ACTIVE
+ 117 | STAR . DELETED
+
+ ACTIVE shift, and go to state 116
+ DELETED shift, and go to state 117
+
+
+State 58
+
+ 120 policy_read_args: policy_asset_name . read_args
+
+ DFNAME shift, and go to state 107
+ CHECK shift, and go to state 108
+ VAR shift, and go to state 109
+ HASH shift, and go to state 110
+ PRINT shift, and go to state 111
+
+ read_args go to state 118
+
+
+State 59
+
+ 21 read_command: READ POLICY policy_read_args .
+
+ $default reduce using rule 21 (read_command)
+
+
+State 60
+
+ 60 random_picked_asset: STAR . ACTIVE
+ 61 | STAR . DELETED
+
+ ACTIVE shift, and go to state 119
+ DELETED shift, and go to state 120
+
+
+State 61
+
+ 22 remove_command: REMOVE SST sst_remove_args .
+
+ $default reduce using rule 22 (remove_command)
+
+
+State 62
+
+ 55 sst_remove_args: random_picked_asset .
+
+ $default reduce using rule 55 (sst_remove_args)
+
+
+State 63
+
+ 54 sst_remove_args: sst_asset_name .
+
+ $default reduce using rule 54 (sst_remove_args)
+
+
+State 64
+
+ 130 key_remove_args: asset_designator .
+
+ $default reduce using rule 130 (key_remove_args)
+
+
+State 65
+
+ 23 remove_command: REMOVE KEY key_remove_args .
+
+ $default reduce using rule 23 (remove_command)
+
+
+State 66
+
+ 24 secure_command: SECURE HASH NEQ . ASSET_IDENTIFIER_LIST
+
+ IDENTIFIER_TOK shift, and go to state 78
+
+ ASSET_IDENTIFIER_LIST go to state 121
+ ASSET_IDENTIFIER go to state 80
+
+
+State 67
+
+ 135 block_content: open_brace lines . close_brace
+
+ CLOSE_BRACE shift, and go to state 122
+
+ close_brace go to state 123
+
+
+State 68
+
+ 12 expect: EXPECT PASS .
+
+ $default reduce using rule 12 (expect)
+
+
+State 69
+
+ 13 expect: EXPECT FAIL .
+
+ $default reduce using rule 13 (expect)
+
+
+State 70
+
+ 14 expect: EXPECT NOTHING .
+
+ $default reduce using rule 14 (expect)
+
+
+State 71
+
+ 147 IDENTIFIER: IDENTIFIER_TOK .
+
+ $default reduce using rule 147 (IDENTIFIER)
+
+
+State 72
+
+ 15 expect: EXPECT IDENTIFIER .
+
+ $default reduce using rule 15 (expect)
+
+
+State 73
+
+ 6 line: command expect SEMICOLON .
+
+ $default reduce using rule 6 (line)
+
+
+State 74
+
+ 133 block: exact_sel_count OF block_content .
+
+ $default reduce using rule 133 (block)
+
+
+State 75
+
+ 134 block: low_sel_count TO high_sel_count . OF block_content
+
+ OF shift, and go to state 124
+
+
+State 76
+
+ 151 high_sel_count: NUMBER .
+
+ $default reduce using rule 151 (high_sel_count)
+
+
+State 77
+
+ 57 asset_designator: NAME STAR .
+
+ $default reduce using rule 57 (asset_designator)
+
+
+State 78
+
+ 146 ASSET_IDENTIFIER: IDENTIFIER_TOK .
+
+ $default reduce using rule 146 (ASSET_IDENTIFIER)
+
+
+State 79
+
+ 56 asset_designator: NAME ASSET_IDENTIFIER_LIST .
+
+ $default reduce using rule 56 (asset_designator)
+
+
+State 80
+
+ 143 ASSET_IDENTIFIER_LIST: ASSET_IDENTIFIER . ASSET_IDENTIFIERS
+
+ IDENTIFIER_TOK shift, and go to state 78
+
+ $default reduce using rule 144 (ASSET_IDENTIFIERS)
+
+ ASSET_IDENTIFIERS go to state 125
+ ASSET_IDENTIFIER go to state 126
+
+
+State 81
+
+ 64 sst_asset_name: UID STAR .
+
+ $default reduce using rule 64 (sst_asset_name)
+
+
+State 82
+
+ 142 ASSET_NUMBER: NUMBER_TOK .
+
+ $default reduce using rule 142 (ASSET_NUMBER)
+
+
+State 83
+
+ 63 sst_asset_name: UID ASSET_NUMBER_LIST .
+
+ $default reduce using rule 63 (sst_asset_name)
+
+
+State 84
+
+ 139 ASSET_NUMBER_LIST: ASSET_NUMBER . ASSET_NUMBERS
+
+ NUMBER_TOK shift, and go to state 82
+
+ $default reduce using rule 140 (ASSET_NUMBERS)
+
+ ASSET_NUMBERS go to state 127
+ ASSET_NUMBER go to state 128
+
+
+State 85
+
+ 33 sst_set_extended_args: FLAG . sst_flags
+
+ NONE shift, and go to state 129
+ WRITE_ONCE shift, and go to state 130
+ NO_RP shift, and go to state 131
+ NO_CONF shift, and go to state 132
+
+ $default reduce using rule 34 (sst_flags)
+
+ sst_flags go to state 133
+ sst_flag go to state 134
+ none go to state 135
+ write_once go to state 136
+ no_rp go to state 137
+ no_conf go to state 138
+
+
+State 86
+
+ 16 set_command: SET SST sst_set_base_args sst_set_extended_args .
+
+ $default reduce using rule 16 (set_command)
+
+
+State 87
+
+ 26 literal_or_random_data: DATA . LITERAL
+ 27 | DATA . STAR
+
+ STAR shift, and go to state 139
+ LITERAL_TOK shift, and go to state 140
+ HEX_LIST shift, and go to state 141
+
+ LITERAL go to state 142
+
+
+State 88
+
+ 31 sst_set_base_args: sst_asset_name DFNAME . sst_asset_set_file_path
+
+ FILE_PATH_TOK shift, and go to state 143
+
+ sst_asset_set_file_path go to state 144
+ FILE_PATH go to state 145
+
+
+State 89
+
+ 30 sst_set_base_args: sst_asset_name VAR . IDENTIFIER
+
+ IDENTIFIER_TOK shift, and go to state 71
+
+ IDENTIFIER go to state 146
+
+
+State 90
+
+ 28 sst_set_base_args: sst_asset_name literal_or_random_data .
+
+ $default reduce using rule 28 (sst_set_base_args)
+
+
+State 91
+
+ 124 key_set_source: POLICY . IDENTIFIER
+
+ IDENTIFIER_TOK shift, and go to state 71
+
+ IDENTIFIER go to state 147
+
+
+State 92
+
+ 128 key_set_args: asset_designator FROM . single_existing_asset POLICY IDENTIFIER
+
+ STAR shift, and go to state 60
+ IDENTIFIER_TOK shift, and go to state 71
+
+ single_existing_asset go to state 148
+ random_picked_asset go to state 149
+ IDENTIFIER go to state 150
+
+
+State 93
+
+ 123 key_set_source: literal_or_random_data .
+ 126 key_data_or_not: literal_or_random_data .
+
+ WITH reduce using rule 126 (key_data_or_not)
+ $default reduce using rule 123 (key_set_source)
+
+
+State 94
+
+ 127 key_set_args: asset_designator key_set_sources .
+
+ $default reduce using rule 127 (key_set_args)
+
+
+State 95
+
+ 122 key_set_sources: key_set_source . key_set_sources
+
+ POLICY shift, and go to state 91
+ DATA shift, and go to state 87
+
+ $default reduce using rule 121 (key_set_sources)
+
+ literal_or_random_data go to state 151
+ key_set_sources go to state 152
+ key_set_source go to state 95
+
+
+State 96
+
+ 129 key_set_args: asset_designator key_data_or_not . WITH policy_specs
+
+ WITH shift, and go to state 153
+
+
+State 97
+
+ 114 policy_asset_spec: NAME STAR .
+
+ $default reduce using rule 114 (policy_asset_spec)
+
+
+State 98
+
+ 113 policy_asset_spec: NAME ASSET_IDENTIFIER_LIST .
+
+ $default reduce using rule 113 (policy_asset_spec)
+
+
+State 99
+
+ 69 policy_usage_list: ATTR . policy_usage policy_usages
+
+ NUMBER_TOK shift, and go to state 154
+ EXPORT shift, and go to state 155
+ COPY shift, and go to state 156
+ ENCRYPT shift, and go to state 157
+ DECRYPT shift, and go to state 158
+ SIGN shift, and go to state 159
+ VERIFY shift, and go to state 160
+ DERIVE shift, and go to state 161
+ NOEXPORT shift, and go to state 162
+ NOCOPY shift, and go to state 163
+ NOENCRYPT shift, and go to state 164
+ NODECRYPT shift, and go to state 165
+ NOSIGN shift, and go to state 166
+ NOVERIFY shift, and go to state 167
+ NODERIVE shift, and go to state 168
+ PERSISTENT shift, and go to state 169
+ VOLATILE shift, and go to state 170
+
+ key_size go to state 171
+ export go to state 172
+ noexport go to state 173
+ copy go to state 174
+ nocopy go to state 175
+ encrypt go to state 176
+ noencrypt go to state 177
+ decrypt go to state 178
+ nodecrypt go to state 179
+ sign go to state 180
+ nosign go to state 181
+ verify go to state 182
+ noverify go to state 183
+ derive go to state 184
+ noderive go to state 185
+ persistent go to state 186
+ volatle go to state 187
+ policy_usage go to state 188
+
+
+State 100
+
+ 105 policy_type: TYPE . IDENTIFIER
+
+ IDENTIFIER_TOK shift, and go to state 71
+
+ IDENTIFIER go to state 189
+
+
+State 101
+
+ 106 policy_algorithm: ALG . IDENTIFIER
+
+ IDENTIFIER_TOK shift, and go to state 71
+
+ IDENTIFIER go to state 190
+
+
+State 102
+
+ 109 policy_spec: policy_usage_list .
+
+ $default reduce using rule 109 (policy_spec)
+
+
+State 103
+
+ 110 policy_spec: policy_type .
+
+ $default reduce using rule 110 (policy_spec)
+
+
+State 104
+
+ 111 policy_spec: policy_algorithm .
+
+ $default reduce using rule 111 (policy_spec)
+
+
+State 105
+
+ 119 policy_set_args: policy_asset_spec policy_specs .
+
+ $default reduce using rule 119 (policy_set_args)
+
+
+State 106
+
+ 108 policy_specs: policy_spec . policy_specs
+
+ ATTR shift, and go to state 99
+ TYPE shift, and go to state 100
+ ALG shift, and go to state 101
+
+ $default reduce using rule 107 (policy_specs)
+
+ policy_usage_list go to state 102
+ policy_type go to state 103
+ policy_algorithm go to state 104
+ policy_specs go to state 191
+ policy_spec go to state 106
+
+
+State 107
+
+ 51 read_args: DFNAME . sst_asset_dump_file_path
+
+ FILE_PATH_TOK shift, and go to state 143
+
+ sst_asset_dump_file_path go to state 192
+ FILE_PATH go to state 193
+
+
+State 108
+
+ 47 read_args: CHECK . read_args_var_name
+ 48 | CHECK . LITERAL
+
+ IDENTIFIER_TOK shift, and go to state 71
+ LITERAL_TOK shift, and go to state 140
+ HEX_LIST shift, and go to state 141
+
+ read_args_var_name go to state 194
+ IDENTIFIER go to state 195
+ LITERAL go to state 196
+
+
+State 109
+
+ 46 read_args: VAR . IDENTIFIER
+
+ IDENTIFIER_TOK shift, and go to state 71
+
+ IDENTIFIER go to state 197
+
+
+State 110
+
+ 50 read_args: HASH .
+
+ $default reduce using rule 50 (read_args)
+
+
+State 111
+
+ 49 read_args: PRINT .
+
+ $default reduce using rule 49 (read_args)
+
+
+State 112
+
+ 45 sst_read_args: sst_asset_name read_args . sst_read_extended_args
+
+ OFFSET shift, and go to state 198
+
+ $default reduce using rule 52 (sst_read_extended_args)
+
+ sst_read_extended_args go to state 199
+
+
+State 113
+
+ 131 key_read_args: asset_designator read_args .
+
+ $default reduce using rule 131 (key_read_args)
+
+
+State 114
+
+ 118 policy_asset_name: KEY IDENTIFIER .
+
+ $default reduce using rule 118 (policy_asset_name)
+
+
+State 115
+
+ 115 policy_asset_name: NAME IDENTIFIER .
+
+ $default reduce using rule 115 (policy_asset_name)
+
+
+State 116
+
+ 116 policy_asset_name: STAR ACTIVE .
+
+ $default reduce using rule 116 (policy_asset_name)
+
+
+State 117
+
+ 117 policy_asset_name: STAR DELETED .
+
+ $default reduce using rule 117 (policy_asset_name)
+
+
+State 118
+
+ 120 policy_read_args: policy_asset_name read_args .
+
+ $default reduce using rule 120 (policy_read_args)
+
+
+State 119
+
+ 60 random_picked_asset: STAR ACTIVE .
+
+ $default reduce using rule 60 (random_picked_asset)
+
+
+State 120
+
+ 61 random_picked_asset: STAR DELETED .
+
+ $default reduce using rule 61 (random_picked_asset)
+
+
+State 121
+
+ 24 secure_command: SECURE HASH NEQ ASSET_IDENTIFIER_LIST .
+
+ $default reduce using rule 24 (secure_command)
+
+
+State 122
+
+ 138 close_brace: CLOSE_BRACE .
+
+ $default reduce using rule 138 (close_brace)
+
+
+State 123
+
+ 135 block_content: open_brace lines close_brace .
+
+ $default reduce using rule 135 (block_content)
+
+
+State 124
+
+ 134 block: low_sel_count TO high_sel_count OF . block_content
+
+ PURPOSE shift, and go to state 1
+ SET shift, and go to state 2
+ READ shift, and go to state 3
+ REMOVE shift, and go to state 4
+ SECURE shift, and go to state 5
+ DONE shift, and go to state 6
+ NUMBER_TOK shift, and go to state 7
+ SHUFFLE shift, and go to state 8
+ OPEN_BRACE shift, and go to state 30
+
+ line go to state 31
+ command go to state 11
+ set_command go to state 12
+ read_command go to state 13
+ remove_command go to state 14
+ secure_command go to state 15
+ done_command go to state 16
+ block go to state 17
+ block_content go to state 200
+ open_brace go to state 33
+ exact_sel_count go to state 18
+ low_sel_count go to state 19
+ NUMBER go to state 20
+
+
+State 125
+
+ 143 ASSET_IDENTIFIER_LIST: ASSET_IDENTIFIER ASSET_IDENTIFIERS .
+
+ $default reduce using rule 143 (ASSET_IDENTIFIER_LIST)
+
+
+State 126
+
+ 145 ASSET_IDENTIFIERS: ASSET_IDENTIFIER . ASSET_IDENTIFIERS
+
+ IDENTIFIER_TOK shift, and go to state 78
+
+ $default reduce using rule 144 (ASSET_IDENTIFIERS)
+
+ ASSET_IDENTIFIERS go to state 201
+ ASSET_IDENTIFIER go to state 126
+
+
+State 127
+
+ 139 ASSET_NUMBER_LIST: ASSET_NUMBER ASSET_NUMBERS .
+
+ $default reduce using rule 139 (ASSET_NUMBER_LIST)
+
+
+State 128
+
+ 141 ASSET_NUMBERS: ASSET_NUMBER . ASSET_NUMBERS
+
+ NUMBER_TOK shift, and go to state 82
+
+ $default reduce using rule 140 (ASSET_NUMBERS)
+
+ ASSET_NUMBERS go to state 202
+ ASSET_NUMBER go to state 128
+
+
+State 129
+
+ 40 none: NONE .
+
+ $default reduce using rule 40 (none)
+
+
+State 130
+
+ 41 write_once: WRITE_ONCE .
+
+ $default reduce using rule 41 (write_once)
+
+
+State 131
+
+ 42 no_rp: NO_RP .
+
+ $default reduce using rule 42 (no_rp)
+
+
+State 132
+
+ 43 no_conf: NO_CONF .
+
+ $default reduce using rule 43 (no_conf)
+
+
+State 133
+
+ 33 sst_set_extended_args: FLAG sst_flags .
+
+ $default reduce using rule 33 (sst_set_extended_args)
+
+
+State 134
+
+ 35 sst_flags: sst_flag . sst_flags
+
+ NONE shift, and go to state 129
+ WRITE_ONCE shift, and go to state 130
+ NO_RP shift, and go to state 131
+ NO_CONF shift, and go to state 132
+
+ $default reduce using rule 34 (sst_flags)
+
+ sst_flags go to state 203
+ sst_flag go to state 134
+ none go to state 135
+ write_once go to state 136
+ no_rp go to state 137
+ no_conf go to state 138
+
+
+State 135
+
+ 36 sst_flag: none .
+
+ $default reduce using rule 36 (sst_flag)
+
+
+State 136
+
+ 37 sst_flag: write_once .
+
+ $default reduce using rule 37 (sst_flag)
+
+
+State 137
+
+ 38 sst_flag: no_rp .
+
+ $default reduce using rule 38 (sst_flag)
+
+
+State 138
+
+ 39 sst_flag: no_conf .
+
+ $default reduce using rule 39 (sst_flag)
+
+
+State 139
+
+ 27 literal_or_random_data: DATA STAR .
+
+ $default reduce using rule 27 (literal_or_random_data)
+
+
+State 140
+
+ 153 LITERAL: LITERAL_TOK .
+
+ $default reduce using rule 153 (LITERAL)
+
+
+State 141
+
+ 154 LITERAL: HEX_LIST .
+
+ $default reduce using rule 154 (LITERAL)
+
+
+State 142
+
+ 26 literal_or_random_data: DATA LITERAL .
+
+ $default reduce using rule 26 (literal_or_random_data)
+
+
+State 143
+
+ 148 FILE_PATH: FILE_PATH_TOK .
+
+ $default reduce using rule 148 (FILE_PATH)
+
+
+State 144
+
+ 31 sst_set_base_args: sst_asset_name DFNAME sst_asset_set_file_path .
+
+ $default reduce using rule 31 (sst_set_base_args)
+
+
+State 145
+
+ 65 sst_asset_set_file_path: FILE_PATH .
+
+ $default reduce using rule 65 (sst_asset_set_file_path)
+
+
+State 146
+
+ 30 sst_set_base_args: sst_asset_name VAR IDENTIFIER .
+
+ $default reduce using rule 30 (sst_set_base_args)
+
+
+State 147
+
+ 124 key_set_source: POLICY IDENTIFIER .
+
+ $default reduce using rule 124 (key_set_source)
+
+
+State 148
+
+ 128 key_set_args: asset_designator FROM single_existing_asset . POLICY IDENTIFIER
+
+ POLICY shift, and go to state 204
+
+
+State 149
+
+ 59 single_existing_asset: random_picked_asset .
+
+ $default reduce using rule 59 (single_existing_asset)
+
+
+State 150
+
+ 58 single_existing_asset: IDENTIFIER .
+
+ $default reduce using rule 58 (single_existing_asset)
+
+
+State 151
+
+ 123 key_set_source: literal_or_random_data .
+
+ $default reduce using rule 123 (key_set_source)
+
+
+State 152
+
+ 122 key_set_sources: key_set_source key_set_sources .
+
+ $default reduce using rule 122 (key_set_sources)
+
+
+State 153
+
+ 129 key_set_args: asset_designator key_data_or_not WITH . policy_specs
+
+ ATTR shift, and go to state 99
+ TYPE shift, and go to state 100
+ ALG shift, and go to state 101
+
+ $default reduce using rule 107 (policy_specs)
+
+ policy_usage_list go to state 102
+ policy_type go to state 103
+ policy_algorithm go to state 104
+ policy_specs go to state 205
+ policy_spec go to state 106
+
+
+State 154
+
+ 68 key_size: NUMBER_TOK .
+
+ $default reduce using rule 68 (key_size)
+
+
+State 155
+
+ 72 export: EXPORT .
+
+ $default reduce using rule 72 (export)
+
+
+State 156
+
+ 74 copy: COPY .
+
+ $default reduce using rule 74 (copy)
+
+
+State 157
+
+ 76 encrypt: ENCRYPT .
+
+ $default reduce using rule 76 (encrypt)
+
+
+State 158
+
+ 78 decrypt: DECRYPT .
+
+ $default reduce using rule 78 (decrypt)
+
+
+State 159
+
+ 80 sign: SIGN .
+
+ $default reduce using rule 80 (sign)
+
+
+State 160
+
+ 82 verify: VERIFY .
+
+ $default reduce using rule 82 (verify)
+
+
+State 161
+
+ 84 derive: DERIVE .
+
+ $default reduce using rule 84 (derive)
+
+
+State 162
+
+ 73 noexport: NOEXPORT .
+
+ $default reduce using rule 73 (noexport)
+
+
+State 163
+
+ 75 nocopy: NOCOPY .
+
+ $default reduce using rule 75 (nocopy)
+
+
+State 164
+
+ 77 noencrypt: NOENCRYPT .
+
+ $default reduce using rule 77 (noencrypt)
+
+
+State 165
+
+ 79 nodecrypt: NODECRYPT .
+
+ $default reduce using rule 79 (nodecrypt)
+
+
+State 166
+
+ 81 nosign: NOSIGN .
+
+ $default reduce using rule 81 (nosign)
+
+
+State 167
+
+ 83 noverify: NOVERIFY .
+
+ $default reduce using rule 83 (noverify)
+
+
+State 168
+
+ 85 noderive: NODERIVE .
+
+ $default reduce using rule 85 (noderive)
+
+
+State 169
+
+ 86 persistent: PERSISTENT .
+
+ $default reduce using rule 86 (persistent)
+
+
+State 170
+
+ 87 volatle: VOLATILE .
+
+ $default reduce using rule 87 (volatle)
+
+
+State 171
+
+ 104 policy_usage: key_size .
+
+ $default reduce using rule 104 (policy_usage)
+
+
+State 172
+
+ 88 policy_usage: export .
+
+ $default reduce using rule 88 (policy_usage)
+
+
+State 173
+
+ 95 policy_usage: noexport .
+
+ $default reduce using rule 95 (policy_usage)
+
+
+State 174
+
+ 89 policy_usage: copy .
+
+ $default reduce using rule 89 (policy_usage)
+
+
+State 175
+
+ 96 policy_usage: nocopy .
+
+ $default reduce using rule 96 (policy_usage)
+
+
+State 176
+
+ 90 policy_usage: encrypt .
+
+ $default reduce using rule 90 (policy_usage)
+
+
+State 177
+
+ 97 policy_usage: noencrypt .
+
+ $default reduce using rule 97 (policy_usage)
+
+
+State 178
+
+ 91 policy_usage: decrypt .
+
+ $default reduce using rule 91 (policy_usage)
+
+
+State 179
+
+ 98 policy_usage: nodecrypt .
+
+ $default reduce using rule 98 (policy_usage)
+
+
+State 180
+
+ 92 policy_usage: sign .
+
+ $default reduce using rule 92 (policy_usage)
+
+
+State 181
+
+ 99 policy_usage: nosign .
+
+ $default reduce using rule 99 (policy_usage)
+
+
+State 182
+
+ 93 policy_usage: verify .
+
+ $default reduce using rule 93 (policy_usage)
+
+
+State 183
+
+ 100 policy_usage: noverify .
+
+ $default reduce using rule 100 (policy_usage)
+
+
+State 184
+
+ 94 policy_usage: derive .
+
+ $default reduce using rule 94 (policy_usage)
+
+
+State 185
+
+ 101 policy_usage: noderive .
+
+ $default reduce using rule 101 (policy_usage)
+
+
+State 186
+
+ 102 policy_usage: persistent .
+
+ $default reduce using rule 102 (policy_usage)
+
+
+State 187
+
+ 103 policy_usage: volatle .
+
+ $default reduce using rule 103 (policy_usage)
+
+
+State 188
+
+ 69 policy_usage_list: ATTR policy_usage . policy_usages
+
+ NUMBER_TOK shift, and go to state 154
+ EXPORT shift, and go to state 155
+ COPY shift, and go to state 156
+ ENCRYPT shift, and go to state 157
+ DECRYPT shift, and go to state 158
+ SIGN shift, and go to state 159
+ VERIFY shift, and go to state 160
+ DERIVE shift, and go to state 161
+ NOEXPORT shift, and go to state 162
+ NOCOPY shift, and go to state 163
+ NOENCRYPT shift, and go to state 164
+ NODECRYPT shift, and go to state 165
+ NOSIGN shift, and go to state 166
+ NOVERIFY shift, and go to state 167
+ NODERIVE shift, and go to state 168
+ PERSISTENT shift, and go to state 169
+ VOLATILE shift, and go to state 170
+
+ $default reduce using rule 70 (policy_usages)
+
+ key_size go to state 171
+ policy_usages go to state 206
+ export go to state 172
+ noexport go to state 173
+ copy go to state 174
+ nocopy go to state 175
+ encrypt go to state 176
+ noencrypt go to state 177
+ decrypt go to state 178
+ nodecrypt go to state 179
+ sign go to state 180
+ nosign go to state 181
+ verify go to state 182
+ noverify go to state 183
+ derive go to state 184
+ noderive go to state 185
+ persistent go to state 186
+ volatle go to state 187
+ policy_usage go to state 207
+
+
+State 189
+
+ 105 policy_type: TYPE IDENTIFIER .
+
+ $default reduce using rule 105 (policy_type)
+
+
+State 190
+
+ 106 policy_algorithm: ALG IDENTIFIER .
+
+ $default reduce using rule 106 (policy_algorithm)
+
+
+State 191
+
+ 108 policy_specs: policy_spec policy_specs .
+
+ $default reduce using rule 108 (policy_specs)
+
+
+State 192
+
+ 51 read_args: DFNAME sst_asset_dump_file_path .
+
+ $default reduce using rule 51 (read_args)
+
+
+State 193
+
+ 67 sst_asset_dump_file_path: FILE_PATH .
+
+ $default reduce using rule 67 (sst_asset_dump_file_path)
+
+
+State 194
+
+ 47 read_args: CHECK read_args_var_name .
+
+ $default reduce using rule 47 (read_args)
+
+
+State 195
+
+ 66 read_args_var_name: IDENTIFIER .
+
+ $default reduce using rule 66 (read_args_var_name)
+
+
+State 196
+
+ 48 read_args: CHECK LITERAL .
+
+ $default reduce using rule 48 (read_args)
+
+
+State 197
+
+ 46 read_args: VAR IDENTIFIER .
+
+ $default reduce using rule 46 (read_args)
+
+
+State 198
+
+ 53 sst_read_extended_args: OFFSET . sst_offset_spec
+
+ NUMBER_TOK shift, and go to state 208
+
+ sst_offset_spec go to state 209
+
+
+State 199
+
+ 45 sst_read_args: sst_asset_name read_args sst_read_extended_args .
+
+ $default reduce using rule 45 (sst_read_args)
+
+
+State 200
+
+ 134 block: low_sel_count TO high_sel_count OF block_content .
+
+ $default reduce using rule 134 (block)
+
+
+State 201
+
+ 145 ASSET_IDENTIFIERS: ASSET_IDENTIFIER ASSET_IDENTIFIERS .
+
+ $default reduce using rule 145 (ASSET_IDENTIFIERS)
+
+
+State 202
+
+ 141 ASSET_NUMBERS: ASSET_NUMBER ASSET_NUMBERS .
+
+ $default reduce using rule 141 (ASSET_NUMBERS)
+
+
+State 203
+
+ 35 sst_flags: sst_flag sst_flags .
+
+ $default reduce using rule 35 (sst_flags)
+
+
+State 204
+
+ 128 key_set_args: asset_designator FROM single_existing_asset POLICY . IDENTIFIER
+
+ IDENTIFIER_TOK shift, and go to state 71
+
+ IDENTIFIER go to state 210
+
+
+State 205
+
+ 129 key_set_args: asset_designator key_data_or_not WITH policy_specs .
+
+ $default reduce using rule 129 (key_set_args)
+
+
+State 206
+
+ 69 policy_usage_list: ATTR policy_usage policy_usages .
+
+ $default reduce using rule 69 (policy_usage_list)
+
+
+State 207
+
+ 71 policy_usages: policy_usage . policy_usages
+
+ NUMBER_TOK shift, and go to state 154
+ EXPORT shift, and go to state 155
+ COPY shift, and go to state 156
+ ENCRYPT shift, and go to state 157
+ DECRYPT shift, and go to state 158
+ SIGN shift, and go to state 159
+ VERIFY shift, and go to state 160
+ DERIVE shift, and go to state 161
+ NOEXPORT shift, and go to state 162
+ NOCOPY shift, and go to state 163
+ NOENCRYPT shift, and go to state 164
+ NODECRYPT shift, and go to state 165
+ NOSIGN shift, and go to state 166
+ NOVERIFY shift, and go to state 167
+ NODERIVE shift, and go to state 168
+ PERSISTENT shift, and go to state 169
+ VOLATILE shift, and go to state 170
+
+ $default reduce using rule 70 (policy_usages)
+
+ key_size go to state 171
+ policy_usages go to state 211
+ export go to state 172
+ noexport go to state 173
+ copy go to state 174
+ nocopy go to state 175
+ encrypt go to state 176
+ noencrypt go to state 177
+ decrypt go to state 178
+ nodecrypt go to state 179
+ sign go to state 180
+ nosign go to state 181
+ verify go to state 182
+ noverify go to state 183
+ derive go to state 184
+ noderive go to state 185
+ persistent go to state 186
+ volatle go to state 187
+ policy_usage go to state 207
+
+
+State 208
+
+ 44 sst_offset_spec: NUMBER_TOK .
+
+ $default reduce using rule 44 (sst_offset_spec)
+
+
+State 209
+
+ 53 sst_read_extended_args: OFFSET sst_offset_spec .
+
+ $default reduce using rule 53 (sst_read_extended_args)
+
+
+State 210
+
+ 128 key_set_args: asset_designator FROM single_existing_asset POLICY IDENTIFIER .
+
+ $default reduce using rule 128 (key_set_args)
+
+
+State 211
+
+ 71 policy_usages: policy_usage policy_usages .
+
+ $default reduce using rule 71 (policy_usages)
diff --git a/tf_fuzz/parser/tf_fuzz_grammar.tab.cpp b/tf_fuzz/parser/tf_fuzz_grammar.tab.cpp
new file mode 100644
index 0000000..6a1e852
--- /dev/null
+++ b/tf_fuzz/parser/tf_fuzz_grammar.tab.cpp
@@ -0,0 +1,3497 @@
+/* A Bison parser, made by GNU Bison 3.0.4. */
+
+/* Bison implementation for Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Bison version. */
+#define YYBISON_VERSION "3.0.4"
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 0
+
+/* Push parsers. */
+#define YYPUSH 0
+
+/* Pull parsers. */
+#define YYPULL 1
+
+
+
+
+/* Copy the first part of user declarations. */
+#line 8 "parser/tf_fuzz_grammar.y" /* yacc.c:339 */
+
+#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 *);
+ /* Sends the yyparse() argument to yyerror(), probably, to print incorrect
+ text it parsed. */
+
+/* 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 is used for now, but this is a good outline of
+ of the template_line class hierarchy. */
+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 only just to
+ show that 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;
+ init_policy_call *iniPolCal = nullptr;
+ reset_policy_call *resPolCal = nullptr;
+ add_policy_usage_call *addPolUsaCal = nullptr;
+ set_policy_lifetime_call *setPolLifCal = nullptr;
+ set_policy_type_call *setPolTypCal = nullptr;
+ set_policy_algorithm_call *setPolAlgCal = nullptr;
+ set_policy_usage_call *setPolUsaCal = nullptr;
+ get_policy_lifetime_call *getPolLifCal = nullptr;
+ get_policy_type_call *getPolTypCal = nullptr;
+ get_policy_algorithm_call *getPolAlgCal = nullptr;
+ get_policy_usage_call *getPolUsaCal = nullptr;
+ get_policy_size_call *getPolSizCal = nullptr;
+ get_key_policy_call *getKeyPolCal = nullptr;
+ key_call *keyCal = nullptr;
+ generate_key_call *genKeyCal = nullptr;
+ create_key_call *creKeyCal = nullptr;
+ copy_key_call *copKeyCal = nullptr;
+ read_key_data_call *reaKeyDatCal = nullptr;
+ remove_key_call *remKeyCal = 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: */
+bool purpose_defined = false;
+psa_asset_usage random_asset = psa_asset_usage::all;
+ /* to 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 parsed_asset; /* everything about identifying assets */
+string target_barrier = ""; /* asset to set and search barrier when re-ordering PSA calls */
+key_policy_info policy_info; /* everything about key policies */
+bool assign_data_var_specified = false;
+string assign_data_var;
+bool print_data = false; /* true to just print asset data to the test log */
+bool hash_data = false; /* true to just print asset data to the test log */
+bool literal_is_string = true;
+ /* if true, literal value is character-string; if false, is list of hex values */
+
+/* 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 parsed_asset */
+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,
+ must inject those results after parsing the expected results. add_expect is a
+ loop index to track where to add results. */
+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;
+
+using namespace std;
+
+
+void set_purp_str (
+ char *raw_purpose, /* the purpose C string from parser */
+ tf_fuzz_info *rsrc /* test resources containing the actual test-purpose string */
+) {
+ size_t l; /* temporary of size_t type */
+ string purp_str = raw_purpose;
+ 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);
+ l = 0;
+ do { /* escape all " chars (if not already escaped) */
+ l = purp_str.find ("\"", l);
+ if ( l < purp_str.length()) { /* did find a quote character */
+ if ( l == 0 /* it's the first character in the string*/
+ || purp_str[l-1] != '\\' /* or it's not already escaped */
+ ) {
+ purp_str.insert (l, "\\"); /* then escape the " char */
+ l++; /* point l to the " again */
+ }
+ l++; /* point l past the " */
+ }
+ } while (l < purp_str.length());
+ rsrc->test_purpose = purp_str;
+}
+
+/* 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,
+ tf_fuzz_info *rsrc /* test resources containing the actual test-purpose string */
+) {
+ 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);
+ }
+ }
+ IVM(cout << "Order of lines in block: " << flush;
+ for (auto i : block_order) {
+ cout << i << " ";
+ }
+ cout << endl;
+ )
+}
+
+/* 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, key_policy_info &policy_info,
+ bool print_data, bool hash_data, string asset_name, string assign_data_var,
+ asset_name_id_info &asset_info, /* 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 instance >0 */
+) {
+ const bool yes_fill_in_template = true; /* just to improve readability */
+ vector<psa_asset*>::iterator t_psa_asset;
+
+ if (fill_in_template) {
+ /* Set basic parameters from the template line: */
+ templateLin->set_data = set_data;
+ templateLin->expect = expect;
+ templateLin->policy_info = policy_info;
+ templateLin->asset_info.id_n_not_name = asset_info.id_n_not_name;
+ templateLin->asset_info.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->print_data = print_data;
+ templateLin->hash_data = hash_data;
+ templateLin->random_asset = random_asset;
+ if ( set_data.literal_data_not_file && !set_data.random_data
+ && set_data.string_specified) {
+ templateLin->set_data.set (literal_data);
+ }
+ /* Save names or IDs to the template-line tracker: */
+ for (auto id_no : asset_info.asset_id_n_vector) {
+ templateLin->asset_info.asset_id_n_vector.push_back (id_no);
+ }
+ asset_info.asset_id_n_vector.clear();
+ for (auto as_name : asset_info.asset_name_vector) {
+ templateLin->asset_info.asset_name_vector.push_back (as_name);
+ }
+ asset_info.asset_name_vector.clear();
+ }
+
+ /* Random asset choice (e.g., *active) case: */
+ if (templateLin->random_asset != psa_asset_usage::all) {
+ /* Just create the call tracker; random name chosen in simulation stage: */
+ templateLin->setup_call (set_data, templateLin->set_data.random_data,
+ yes_fill_in_template, create_call_bool,
+ templateLin, rsrc );
+ } else if (asset_info.id_n_not_name) {
+ /* Not random asset; asset(s) by ID rather than name. Go through all
+ specified asset IDs: */
+ uint64_t id_no;
+ for (auto id_n : templateLin->asset_info.asset_id_n_vector) {
+ id_no = id_n + (uint64_t) instance * 10000UL;
+ templateLin->asset_info.set_id_n(id_no); /* just a holder */
+ asset_name = templateLin->asset_info.make_id_n_based_name (id_no);
+ templateLin->asset_info.set_calc_name (asset_name);
+ templateLin->expect.data_var = var_name;
+ if (!set_data.literal_data_not_file) {
+ templateLin->set_data.set_file (set_data.file_path);
+ }
+ templateLin->setup_call (set_data, templateLin->set_data.random_data,
+ fill_in_template, create_call_bool,
+ templateLin, rsrc );
+ }
+ } else {
+ /* Not random asset, asset(s) specified by name. Go through all specified
+ asset names: */
+ for (auto as_name : templateLin->asset_info.asset_name_vector) {
+ /* Also copy into template line object's local vector: */
+ if (instance > 0) {
+ templateLin->asset_info.set_name (as_name + "_" + to_string (instance));
+ } else {
+ templateLin->asset_info.set_name (as_name);
+ }
+ /* Give each occurrence a different random ID: */
+ templateLin->asset_info.set_id_n (100 + (rand() % 10000));
+ /* TODO: unlikely, but this *could* alias! */
+ templateLin->setup_call (set_data, templateLin->set_data.random_data,
+ yes_fill_in_template, create_call_bool,
+ templateLin, rsrc );
+ }
+ }
+}
+
+
+#line 409 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:339 */
+
+# ifndef YY_NULLPTR
+# if defined __cplusplus && 201103L <= __cplusplus
+# define YY_NULLPTR nullptr
+# else
+# define YY_NULLPTR 0
+# endif
+# endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 1
+#endif
+
+/* In a future release of Bison, this section will be replaced
+ by #include "tf_fuzz_grammar.tab.hpp". */
+#ifndef YY_YY_PARSER_TF_FUZZ_GRAMMAR_TAB_HPP_INCLUDED
+# define YY_YY_PARSER_TF_FUZZ_GRAMMAR_TAB_HPP_INCLUDED
+/* Debug traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int yydebug;
+#endif
+
+/* Token type. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ enum yytokentype
+ {
+ PURPOSE = 258,
+ RAW_TEXT = 259,
+ SET = 260,
+ READ = 261,
+ REMOVE = 262,
+ SECURE = 263,
+ DONE = 264,
+ SST = 265,
+ KEY = 266,
+ POLICY = 267,
+ NAME = 268,
+ UID = 269,
+ STAR = 270,
+ ACTIVE = 271,
+ DELETED = 272,
+ EQUAL = 273,
+ DATA = 274,
+ DFNAME = 275,
+ FLAG = 276,
+ NONE = 277,
+ WRITE_ONCE = 278,
+ NO_RP = 279,
+ NO_CONF = 280,
+ OFFSET = 281,
+ CHECK = 282,
+ VAR = 283,
+ HASH = 284,
+ NEQ = 285,
+ PRINT = 286,
+ EXPECT = 287,
+ PASS = 288,
+ FAIL = 289,
+ NOTHING = 290,
+ ERROR = 291,
+ IDENTIFIER_TOK = 292,
+ LITERAL_TOK = 293,
+ HEX_LIST = 294,
+ FILE_PATH_TOK = 295,
+ NUMBER_TOK = 296,
+ SEMICOLON = 297,
+ SHUFFLE = 298,
+ TO = 299,
+ OF = 300,
+ OPEN_BRACE = 301,
+ CLOSE_BRACE = 302,
+ ATTR = 303,
+ TYPE = 304,
+ ALG = 305,
+ EXPORT = 306,
+ COPY = 307,
+ ENCRYPT = 308,
+ DECRYPT = 309,
+ SIGN = 310,
+ VERIFY = 311,
+ DERIVE = 312,
+ NOEXPORT = 313,
+ NOCOPY = 314,
+ NOENCRYPT = 315,
+ NODECRYPT = 316,
+ NOSIGN = 317,
+ NOVERIFY = 318,
+ NODERIVE = 319,
+ PERSISTENT = 320,
+ VOLATILE = 321,
+ FROM = 322,
+ WITH = 323
+ };
+#endif
+
+/* Value type. */
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+
+union YYSTYPE
+{
+#line 353 "parser/tf_fuzz_grammar.y" /* yacc.c:355 */
+int valueN; int tokenN; char *str;
+
+#line 521 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:355 */
+};
+
+typedef union YYSTYPE YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+/* Location type. */
+#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
+typedef struct YYLTYPE YYLTYPE;
+struct YYLTYPE
+{
+ int first_line;
+ int first_column;
+ int last_line;
+ int last_column;
+};
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+#endif
+
+
+extern YYSTYPE yylval;
+extern YYLTYPE yylloc;
+int yyparse (tf_fuzz_info *rsrc);
+
+#endif /* !YY_YY_PARSER_TF_FUZZ_GRAMMAR_TAB_HPP_INCLUDED */
+
+/* Copy the second part of user declarations. */
+
+#line 552 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:358 */
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#else
+typedef signed char yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif ! defined YYSIZE_T
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+# if ENABLE_NLS
+# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_(Msgid) dgettext ("bison-runtime", Msgid)
+# endif
+# endif
+# ifndef YY_
+# define YY_(Msgid) Msgid
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE
+# if (defined __GNUC__ \
+ && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \
+ || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
+# define YY_ATTRIBUTE(Spec) __attribute__(Spec)
+# else
+# define YY_ATTRIBUTE(Spec) /* empty */
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE_PURE
+# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__))
+#endif
+
+#ifndef YY_ATTRIBUTE_UNUSED
+# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
+#endif
+
+#if !defined _Noreturn \
+ && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
+# if defined _MSC_VER && 1200 <= _MSC_VER
+# define _Noreturn __declspec (noreturn)
+# else
+# define _Noreturn YY_ATTRIBUTE ((__noreturn__))
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E. */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(E) ((void) (E))
+#else
+# define YYUSE(E) /* empty */
+#endif
+
+#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+/* Suppress an incorrect diagnostic about yylval being uninitialized. */
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+ _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+ _Pragma ("GCC diagnostic pop")
+#else
+# define YY_INITIAL_VALUE(Value) Value
+#endif
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
+#endif
+#ifndef YY_INITIAL_VALUE
+# define YY_INITIAL_VALUE(Value) /* Nothing. */
+#endif
+
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
+# else
+# define YYSTACK_ALLOC alloca
+# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+ /* Use EXIT_SUCCESS as a witness for stdlib.h. */
+# ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+# endif
+# endif
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's 'empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+# ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
+ to allow for a few compiler-allocated temporary stack slots. */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+# endif
+# else
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# ifndef YYSTACK_ALLOC_MAXIMUM
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+# endif
+# if (defined __cplusplus && ! defined EXIT_SUCCESS \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined EXIT_SUCCESS
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined EXIT_SUCCESS
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \
+ && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ yytype_int16 yyss_alloc;
+ YYSTYPE yyvs_alloc;
+ YYLTYPE yyls_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \
+ + 2 * YYSTACK_GAP_MAXIMUM)
+
+# define YYCOPY_NEEDED 1
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
+ Stack = &yyptr->Stack_alloc; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (0)
+
+#endif
+
+#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
+/* Copy COUNT objects from SRC to DST. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(Dst, Src, Count) \
+ __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
+# else
+# define YYCOPY(Dst, Src, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (Dst)[yyi] = (Src)[yyi]; \
+ } \
+ while (0)
+# endif
+# endif
+#endif /* !YYCOPY_NEEDED */
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 34
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 159
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 69
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 82
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 155
+/* YYNSTATES -- Number of states. */
+#define YYNSTATES 212
+
+/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
+ by yylex, with out-of-bounds checking. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 323
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
+ as returned by yylex, without out-of-bounds checking. */
+static const yytype_uint8 yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
+ 65, 66, 67, 68
+};
+
+#if YYDEBUG
+ /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
+static const yytype_uint16 yyrline[] =
+{
+ 0, 378, 378, 379, 390, 409, 451, 475, 501, 504,
+ 507, 510, 513, 519, 524, 529, 534, 543, 555, 568,
+ 583, 595, 607, 622, 634, 649, 679, 691, 701, 712,
+ 713, 718, 726, 736, 737, 744, 745, 751, 751, 751,
+ 751, 753, 760, 767, 775, 784, 793, 799, 807, 816,
+ 826, 838, 851, 859, 860, 868, 868, 875, 883, 896,
+ 904, 908, 914, 923, 924, 932, 944, 951, 959, 967,
+ 974, 977, 978, 984, 990, 996, 1002, 1008, 1014, 1020,
+ 1026, 1032, 1038, 1044, 1050, 1056, 1062, 1068, 1074, 1081,
+ 1081, 1081, 1081, 1081, 1081, 1081, 1082, 1082, 1082, 1082,
+ 1082, 1082, 1083, 1083, 1083, 1083, 1089, 1098, 1107, 1108,
+ 1114, 1114, 1114, 1117, 1118, 1126, 1140, 1150, 1157, 1164,
+ 1176, 1182, 1188, 1189, 1196, 1200, 1210, 1211, 1218, 1224,
+ 1231, 1243, 1250, 1257, 1268, 1274, 1288, 1291, 1298, 1307,
+ 1317, 1320, 1321, 1324, 1337, 1340, 1341, 1344, 1353, 1361,
+ 1371, 1380, 1388, 1399, 1407, 1413
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || 1
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "PURPOSE", "RAW_TEXT", "SET", "READ",
+ "REMOVE", "SECURE", "DONE", "SST", "KEY", "POLICY", "NAME", "UID",
+ "STAR", "ACTIVE", "DELETED", "EQUAL", "DATA", "DFNAME", "FLAG", "NONE",
+ "WRITE_ONCE", "NO_RP", "NO_CONF", "OFFSET", "CHECK", "VAR", "HASH",
+ "NEQ", "PRINT", "EXPECT", "PASS", "FAIL", "NOTHING", "ERROR",
+ "IDENTIFIER_TOK", "LITERAL_TOK", "HEX_LIST", "FILE_PATH_TOK",
+ "NUMBER_TOK", "SEMICOLON", "SHUFFLE", "TO", "OF", "OPEN_BRACE",
+ "CLOSE_BRACE", "ATTR", "TYPE", "ALG", "EXPORT", "COPY", "ENCRYPT",
+ "DECRYPT", "SIGN", "VERIFY", "DERIVE", "NOEXPORT", "NOCOPY", "NOENCRYPT",
+ "NODECRYPT", "NOSIGN", "NOVERIFY", "NODERIVE", "PERSISTENT", "VOLATILE",
+ "FROM", "WITH", "$accept", "lines", "line", "command", "expect",
+ "set_command", "read_command", "remove_command", "secure_command",
+ "done_command", "literal_or_random_data", "sst_set_base_args",
+ "sst_set_extended_args", "sst_flags", "sst_flag", "none", "write_once",
+ "no_rp", "no_conf", "sst_offset_spec", "sst_read_args", "read_args",
+ "sst_read_extended_args", "sst_remove_args", "asset_designator",
+ "single_existing_asset", "random_picked_asset", "sst_asset_name",
+ "sst_asset_set_file_path", "read_args_var_name",
+ "sst_asset_dump_file_path", "key_size", "policy_usage_list",
+ "policy_usages", "export", "noexport", "copy", "nocopy", "encrypt",
+ "noencrypt", "decrypt", "nodecrypt", "sign", "nosign", "verify",
+ "noverify", "derive", "noderive", "persistent", "volatle",
+ "policy_usage", "policy_type", "policy_algorithm", "policy_specs",
+ "policy_spec", "policy_asset_spec", "policy_asset_name",
+ "policy_set_args", "policy_read_args", "key_set_sources",
+ "key_set_source", "key_data_or_not", "key_set_args", "key_remove_args",
+ "key_read_args", "block", "block_content", "open_brace", "close_brace",
+ "ASSET_NUMBER_LIST", "ASSET_NUMBERS", "ASSET_NUMBER",
+ "ASSET_IDENTIFIER_LIST", "ASSET_IDENTIFIERS", "ASSET_IDENTIFIER",
+ "IDENTIFIER", "FILE_PATH", "exact_sel_count", "low_sel_count",
+ "high_sel_count", "NUMBER", "LITERAL", YY_NULLPTR
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[NUM] -- (External) token number corresponding to the
+ (internal) symbol number NUM (which must be that of a token). */
+static const yytype_uint16 yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+ 275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
+ 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
+ 295, 296, 297, 298, 299, 300, 301, 302, 303, 304,
+ 305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
+ 315, 316, 317, 318, 319, 320, 321, 322, 323
+};
+# endif
+
+#define YYPACT_NINF -102
+
+#define yypact_value_is_default(Yystate) \
+ (!!((Yystate) == (-102)))
+
+#define YYTABLE_NINF -152
+
+#define yytable_value_is_error(Yytable_value) \
+ 0
+
+ /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+static const yytype_int16 yypact[] =
+{
+ 35, -102, 75, 104, 47, -17, -102, -102, 20, 64,
+ 35, -23, -102, -102, -102, -102, -102, -102, 30, 39,
+ 73, 37, 95, 112, 37, 95, 7, 106, 95, 103,
+ -102, -102, -102, 35, -102, -102, 72, -102, 92, 20,
+ 94, 32, -2, 116, -102, -4, -8, -102, 33, 74,
+ -102, -102, 53, 53, -102, 99, 99, 113, 53, -102,
+ 115, -102, -102, -102, -102, -102, 101, 93, -102, -102,
+ -102, -102, -102, -102, -102, 96, -102, -102, -102, -102,
+ 101, -102, -102, -102, 98, 88, -102, -7, 102, 99,
+ -102, 99, 34, 76, -102, 2, 77, -102, -102, 38,
+ 99, 99, -102, -102, -102, -102, 74, 102, 89, 99,
+ -102, -102, 117, -102, -102, -102, -102, -102, -102, -102,
+ -102, -102, -102, -102, 20, -102, 101, -102, 98, -102,
+ -102, -102, -102, -102, 88, -102, -102, -102, -102, -102,
+ -102, -102, -102, -102, -102, -102, -102, -102, 134, -102,
+ -102, -102, -102, 74, -102, -102, -102, -102, -102, -102,
+ -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+ -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+ -102, -102, -102, -102, -102, -102, -102, -102, 38, -102,
+ -102, -102, -102, -102, -102, -102, -102, -102, 107, -102,
+ -102, -102, -102, -102, 99, -102, -102, 38, -102, -102,
+ -102, -102
+};
+
+ /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+ Performed when YYTABLE does not specify something else to do. Zero
+ means the default is an error. */
+static const yytype_uint8 yydefact[] =
+{
+ 2, 4, 0, 0, 0, 0, 26, 153, 0, 0,
+ 2, 0, 8, 10, 9, 11, 12, 5, 0, 0,
+ 150, 0, 0, 113, 0, 0, 0, 0, 0, 0,
+ 138, 137, 133, 2, 1, 3, 0, 6, 0, 0,
+ 0, 0, 0, 33, 63, 30, 122, 18, 0, 108,
+ 19, 20, 0, 0, 21, 0, 0, 0, 0, 22,
+ 0, 23, 56, 55, 131, 24, 0, 0, 13, 14,
+ 15, 148, 16, 7, 134, 0, 152, 58, 147, 57,
+ 145, 65, 143, 64, 141, 35, 17, 0, 0, 0,
+ 29, 0, 0, 124, 128, 122, 0, 115, 114, 0,
+ 0, 0, 110, 111, 112, 120, 108, 0, 0, 0,
+ 51, 50, 53, 132, 119, 116, 117, 118, 121, 61,
+ 62, 25, 139, 136, 0, 144, 145, 140, 141, 41,
+ 42, 43, 44, 34, 35, 37, 38, 39, 40, 28,
+ 154, 155, 27, 149, 32, 66, 31, 125, 0, 60,
+ 59, 124, 123, 108, 69, 73, 75, 77, 79, 81,
+ 83, 85, 74, 76, 78, 80, 82, 84, 86, 87,
+ 88, 105, 89, 96, 90, 97, 91, 98, 92, 99,
+ 93, 100, 94, 101, 95, 102, 103, 104, 71, 106,
+ 107, 109, 52, 68, 48, 67, 49, 47, 0, 46,
+ 135, 146, 142, 36, 0, 130, 70, 71, 45, 54,
+ 129, 72
+};
+
+ /* YYPGOTO[NTERM-NUM]. */
+static const yytype_int8 yypgoto[] =
+{
+ -102, -3, -6, -102, -102, -102, -102, -102, -102, -102,
+ -40, -102, -102, 13, -102, -102, -102, -102, -102, -102,
+ -102, 14, -102, -102, 40, -102, 58, 50, -102, -102,
+ -102, -102, -102, -56, -102, -102, -102, -102, -102, -102,
+ -102, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+ 54, -102, -102, -101, -102, -102, -102, -102, -102, 57,
+ -102, -102, -102, -102, -102, -102, -36, -102, -102, -102,
+ 26, 114, -31, 29, -70, -55, 51, -102, -102, -102,
+ 119, 49
+};
+
+ /* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int16 yydefgoto[] =
+{
+ -1, 9, 10, 11, 38, 12, 13, 14, 15, 16,
+ 90, 43, 86, 133, 134, 135, 136, 137, 138, 209,
+ 51, 112, 199, 61, 44, 148, 62, 45, 144, 194,
+ 192, 171, 102, 206, 172, 173, 174, 175, 176, 177,
+ 178, 179, 180, 181, 182, 183, 184, 185, 186, 187,
+ 207, 103, 104, 105, 106, 49, 58, 50, 59, 94,
+ 95, 96, 47, 65, 54, 17, 32, 33, 123, 83,
+ 127, 128, 79, 125, 80, 72, 145, 18, 19, 75,
+ 20, 142
+};
+
+ /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule whose
+ number is the opposite. If YYTABLE_NINF, syntax error. */
+static const yytype_int16 yytable[] =
+{
+ 114, 115, 31, 74, 91, 191, 93, 35, 139, 36,
+ 126, 87, 29, 81, 91, 87, 88, 98, 55, 37,
+ 56, 87, 57, 1, 89, 2, 3, 4, 5, 6,
+ 67, 140, 141, 31, 146, 121, 147, 150, 1, 82,
+ 2, 3, 4, 5, 6, 189, 190, 77, 97, 60,
+ 41, 42, 205, 195, 197, 151, 126, 27, 28, 92,
+ -126, 7, 46, 8, 34, 53, 30, 113, 64, 78,
+ 78, 71, 118, 107, 52, 39, 7, 63, 8, 154,
+ 108, 109, 110, 40, 111, 21, 22, 23, 200, 155,
+ 156, 157, 158, 159, 160, 161, 162, 163, 164, 165,
+ 166, 167, 168, 169, 170, 68, 69, 70, 41, 71,
+ 129, 130, 131, 132, 24, 25, 26, -151, 31, 41,
+ 42, 60, 99, 100, 101, 48, 71, 140, 141, 116,
+ 117, 119, 120, 66, 73, 7, 71, 85, 78, 82,
+ 122, 124, 143, 198, -127, 153, 204, 203, 208, 210,
+ 149, 211, 152, 188, 202, 201, 84, 196, 193, 76
+};
+
+static const yytype_uint8 yycheck[] =
+{
+ 55, 56, 8, 39, 12, 106, 46, 10, 15, 32,
+ 80, 19, 29, 15, 12, 19, 20, 48, 11, 42,
+ 13, 19, 15, 3, 28, 5, 6, 7, 8, 9,
+ 33, 38, 39, 39, 89, 66, 91, 92, 3, 41,
+ 5, 6, 7, 8, 9, 100, 101, 15, 15, 15,
+ 13, 14, 153, 108, 109, 95, 126, 10, 11, 67,
+ 68, 41, 22, 43, 0, 25, 46, 53, 28, 37,
+ 37, 37, 58, 20, 24, 45, 41, 27, 43, 41,
+ 27, 28, 29, 44, 31, 10, 11, 12, 124, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 33, 34, 35, 13, 37,
+ 22, 23, 24, 25, 10, 11, 12, 44, 124, 13,
+ 14, 15, 48, 49, 50, 13, 37, 38, 39, 16,
+ 17, 16, 17, 30, 42, 41, 37, 21, 37, 41,
+ 47, 45, 40, 26, 68, 68, 12, 134, 41, 204,
+ 92, 207, 95, 99, 128, 126, 42, 108, 107, 40
+};
+
+ /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const yytype_uint8 yystos[] =
+{
+ 0, 3, 5, 6, 7, 8, 9, 41, 43, 70,
+ 71, 72, 74, 75, 76, 77, 78, 134, 146, 147,
+ 149, 10, 11, 12, 10, 11, 12, 10, 11, 29,
+ 46, 71, 135, 136, 0, 70, 32, 42, 73, 45,
+ 44, 13, 14, 80, 93, 96, 93, 131, 13, 124,
+ 126, 89, 96, 93, 133, 11, 13, 15, 125, 127,
+ 15, 92, 95, 96, 93, 132, 30, 70, 33, 34,
+ 35, 37, 144, 42, 135, 148, 149, 15, 37, 141,
+ 143, 15, 41, 138, 140, 21, 81, 19, 20, 28,
+ 79, 12, 67, 79, 128, 129, 130, 15, 141, 48,
+ 49, 50, 101, 120, 121, 122, 123, 20, 27, 28,
+ 29, 31, 90, 90, 144, 144, 16, 17, 90, 16,
+ 17, 141, 47, 137, 45, 142, 143, 139, 140, 22,
+ 23, 24, 25, 82, 83, 84, 85, 86, 87, 15,
+ 38, 39, 150, 40, 97, 145, 144, 144, 94, 95,
+ 144, 79, 128, 68, 41, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66, 100, 103, 104, 105, 106, 107, 108, 109, 110,
+ 111, 112, 113, 114, 115, 116, 117, 118, 119, 144,
+ 144, 122, 99, 145, 98, 144, 150, 144, 26, 91,
+ 135, 142, 139, 82, 12, 122, 102, 119, 41, 88,
+ 144, 102
+};
+
+ /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const yytype_uint8 yyr1[] =
+{
+ 0, 69, 70, 70, 71, 71, 71, 71, 72, 72,
+ 72, 72, 72, 73, 73, 73, 73, 74, 74, 74,
+ 75, 75, 75, 76, 76, 77, 78, 79, 79, 80,
+ 80, 80, 80, 81, 81, 82, 82, 83, 83, 83,
+ 83, 84, 85, 86, 87, 88, 89, 90, 90, 90,
+ 90, 90, 90, 91, 91, 92, 92, 93, 93, 94,
+ 94, 95, 95, 96, 96, 96, 97, 98, 99, 100,
+ 101, 102, 102, 103, 104, 105, 106, 107, 108, 109,
+ 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
+ 119, 119, 119, 119, 119, 119, 119, 119, 119, 119,
+ 119, 119, 119, 119, 119, 119, 120, 121, 122, 122,
+ 123, 123, 123, 124, 124, 124, 125, 125, 125, 125,
+ 126, 127, 128, 128, 129, 129, 130, 130, 131, 131,
+ 131, 132, 133, 134, 134, 134, 135, 135, 136, 137,
+ 138, 139, 139, 140, 141, 142, 142, 143, 144, 145,
+ 146, 147, 148, 149, 150, 150
+};
+
+ /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
+static const yytype_uint8 yyr2[] =
+{
+ 0, 2, 0, 2, 1, 1, 2, 3, 1, 1,
+ 1, 1, 1, 2, 2, 2, 2, 4, 3, 3,
+ 3, 3, 3, 3, 3, 4, 1, 2, 2, 2,
+ 1, 3, 3, 0, 2, 0, 2, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 3, 2, 2, 2,
+ 1, 1, 2, 0, 2, 1, 1, 2, 2, 1,
+ 1, 2, 2, 1, 2, 2, 1, 1, 1, 1,
+ 3, 0, 2, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 2, 2, 0, 2,
+ 1, 1, 1, 0, 2, 2, 2, 2, 2, 2,
+ 2, 2, 0, 2, 1, 2, 0, 1, 2, 5,
+ 4, 1, 2, 2, 3, 5, 3, 1, 1, 1,
+ 2, 0, 2, 1, 2, 0, 2, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1
+};
+
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ YYPOPSTACK (yylen); \
+ yystate = *yyssp; \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (rsrc, YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+while (0)
+
+/* Error token number */
+#define YYTERROR 1
+#define YYERRCODE 256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+ If N is 0, then set CURRENT to the empty location which ends
+ the previous symbol: RHS[0] (always defined). */
+
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (N) \
+ { \
+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC (Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC (Rhs, 0).last_column; \
+ } \
+ while (0)
+#endif
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (0)
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+ This macro was not mandated originally: define only if we know
+ we won't break user code: when these are the locations we know. */
+
+#ifndef YY_LOCATION_PRINT
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+
+/* Print *YYLOCP on YYO. Private, do not rely on its existence. */
+
+YY_ATTRIBUTE_UNUSED
+static unsigned
+yy_location_print_ (FILE *yyo, YYLTYPE const * const yylocp)
+{
+ unsigned res = 0;
+ int end_col = 0 != yylocp->last_column ? yylocp->last_column - 1 : 0;
+ if (0 <= yylocp->first_line)
+ {
+ res += YYFPRINTF (yyo, "%d", yylocp->first_line);
+ if (0 <= yylocp->first_column)
+ res += YYFPRINTF (yyo, ".%d", yylocp->first_column);
+ }
+ if (0 <= yylocp->last_line)
+ {
+ if (yylocp->first_line < yylocp->last_line)
+ {
+ res += YYFPRINTF (yyo, "-%d", yylocp->last_line);
+ if (0 <= end_col)
+ res += YYFPRINTF (yyo, ".%d", end_col);
+ }
+ else if (0 <= end_col && yylocp->first_column < end_col)
+ res += YYFPRINTF (yyo, "-%d", end_col);
+ }
+ return res;
+ }
+
+# define YY_LOCATION_PRINT(File, Loc) \
+ yy_location_print_ (File, &(Loc))
+
+# else
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value, Location, rsrc); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (0)
+
+
+/*----------------------------------------.
+| Print this symbol's value on YYOUTPUT. |
+`----------------------------------------*/
+
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, tf_fuzz_info *rsrc)
+{
+ FILE *yyo = yyoutput;
+ YYUSE (yyo);
+ YYUSE (yylocationp);
+ YYUSE (rsrc);
+ if (!yyvaluep)
+ return;
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# endif
+ YYUSE (yytype);
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, tf_fuzz_info *rsrc)
+{
+ YYFPRINTF (yyoutput, "%s %s (",
+ yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
+
+ YY_LOCATION_PRINT (yyoutput, *yylocationp);
+ YYFPRINTF (yyoutput, ": ");
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, rsrc);
+ YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (; yybottom <= yytop; yybottom++)
+ {
+ int yybot = *yybottom;
+ YYFPRINTF (stderr, " %d", yybot);
+ }
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (0)
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+static void
+yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, tf_fuzz_info *rsrc)
+{
+ unsigned long int yylno = yyrline[yyrule];
+ int yynrhs = yyr2[yyrule];
+ int yyi;
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ YYFPRINTF (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr,
+ yystos[yyssp[yyi + 1 - yynrhs]],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ , &(yylsp[(yyi + 1) - (yynrhs)]) , rsrc);
+ YYFPRINTF (stderr, "\n");
+ }
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyssp, yyvsp, yylsp, Rule, rsrc); \
+} while (0)
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined __GLIBC__ && defined _STRING_H
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+static YYSIZE_T
+yystrlen (const char *yystr)
+{
+ YYSIZE_T yylen;
+ for (yylen = 0; yystr[yylen]; yylen++)
+ continue;
+ return yylen;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+{
+ char *yyd = yydest;
+ const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+ quotes and backslashes, so that it's suitable for yyerror. The
+ heuristic is that double-quoting is unnecessary unless the string
+ contains an apostrophe, a comma, or backslash (other than
+ backslash-backslash). YYSTR is taken from yytname. If YYRES is
+ null, do not copy; instead, return the length of what the result
+ would have been. */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+ if (*yystr == '"')
+ {
+ YYSIZE_T yyn = 0;
+ char const *yyp = yystr;
+
+ for (;;)
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
+ do_not_strip_quotes: ;
+ }
+
+ if (! yyres)
+ return yystrlen (yystr);
+
+ return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
+ about the unexpected token YYTOKEN for the state stack whose top is
+ YYSSP.
+
+ Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is
+ not large enough to hold the message. In that case, also set
+ *YYMSG_ALLOC to the required number of bytes. Return 2 if the
+ required number of bytes is too large to store. */
+static int
+yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
+ yytype_int16 *yyssp, int yytoken)
+{
+ YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
+ YYSIZE_T yysize = yysize0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ /* Internationalized format string. */
+ const char *yyformat = YY_NULLPTR;
+ /* Arguments of yyformat. */
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ /* Number of reported tokens (one for the "unexpected", one per
+ "expected"). */
+ int yycount = 0;
+
+ /* There are many possibilities here to consider:
+ - If this state is a consistent state with a default action, then
+ the only way this function was invoked is if the default action
+ is an error action. In that case, don't check for expected
+ tokens because there are none.
+ - The only way there can be no lookahead present (in yychar) is if
+ this state is a consistent state with a default action. Thus,
+ detecting the absence of a lookahead is sufficient to determine
+ that there is no unexpected or expected token to report. In that
+ case, just report a simple "syntax error".
+ - Don't assume there isn't a lookahead just because this state is a
+ consistent state with a default action. There might have been a
+ previous inconsistent state, consistent state with a non-default
+ action, or user semantic action that manipulated yychar.
+ - Of course, the expected token list depends on states to have
+ correct lookahead information, and it depends on the parser not
+ to perform extra reductions after fetching a lookahead from the
+ scanner and before detecting a syntax error. Thus, state merging
+ (from LALR or IELR) and default reductions corrupt the expected
+ token list. However, the list is correct for canonical LR with
+ one exception: it will still contain any token that will not be
+ accepted due to an error action in a later state.
+ */
+ if (yytoken != YYEMPTY)
+ {
+ int yyn = yypact[*yyssp];
+ yyarg[yycount++] = yytname[yytoken];
+ if (!yypact_value_is_default (yyn))
+ {
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. In other words, skip the first -YYN actions for
+ this state because they are default actions. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yyx;
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
+ && !yytable_value_is_error (yytable[yyx + yyn]))
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ {
+ YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
+ if (! (yysize <= yysize1
+ && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ return 2;
+ yysize = yysize1;
+ }
+ }
+ }
+ }
+
+ switch (yycount)
+ {
+# define YYCASE_(N, S) \
+ case N: \
+ yyformat = S; \
+ break
+ YYCASE_(0, YY_("syntax error"));
+ YYCASE_(1, YY_("syntax error, unexpected %s"));
+ YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
+ YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
+ YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
+ YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
+# undef YYCASE_
+ }
+
+ {
+ YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
+ if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ return 2;
+ yysize = yysize1;
+ }
+
+ if (*yymsg_alloc < yysize)
+ {
+ *yymsg_alloc = 2 * yysize;
+ if (! (yysize <= *yymsg_alloc
+ && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
+ *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
+ return 1;
+ }
+
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ {
+ char *yyp = *yymsg;
+ int yyi = 0;
+ while ((*yyp = *yyformat) != '\0')
+ if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyformat += 2;
+ }
+ else
+ {
+ yyp++;
+ yyformat++;
+ }
+ }
+ return 0;
+}
+#endif /* YYERROR_VERBOSE */
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, tf_fuzz_info *rsrc)
+{
+ YYUSE (yyvaluep);
+ YYUSE (yylocationp);
+ YYUSE (rsrc);
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ YYUSE (yytype);
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+}
+
+
+
+
+/* The lookahead symbol. */
+int yychar;
+
+/* The semantic value of the lookahead symbol. */
+YYSTYPE yylval;
+/* Location data for the lookahead symbol. */
+YYLTYPE yylloc
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+ = { 1, 1, 1, 1 }
+# endif
+;
+/* Number of syntax errors so far. */
+int yynerrs;
+
+
+/*----------.
+| yyparse. |
+`----------*/
+
+int
+yyparse (tf_fuzz_info *rsrc)
+{
+ int yystate;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+
+ /* The stacks and their tools:
+ 'yyss': related to states.
+ 'yyvs': related to semantic values.
+ 'yyls': related to locations.
+
+ Refer to the stacks through separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss;
+ yytype_int16 *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs;
+ YYSTYPE *yyvsp;
+
+ /* The location stack. */
+ YYLTYPE yylsa[YYINITDEPTH];
+ YYLTYPE *yyls;
+ YYLTYPE *yylsp;
+
+ /* The locations where the error started and ended. */
+ YYLTYPE yyerror_range[3];
+
+ YYSIZE_T yystacksize;
+
+ int yyn;
+ int yyresult;
+ /* Lookahead token as an internal (translated) token number. */
+ int yytoken = 0;
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+ YYLTYPE yyloc;
+
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N))
+
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
+
+ yyssp = yyss = yyssa;
+ yyvsp = yyvs = yyvsa;
+ yylsp = yyls = yylsa;
+ yystacksize = YYINITDEPTH;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+ yylsp[0] = yylloc;
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. So pushing a state here evens the stacks. */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ yytype_int16 *yyss1 = yyss;
+ YYLTYPE *yyls1 = yyls;
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+ &yyls1, yysize * sizeof (*yylsp),
+ &yystacksize);
+
+ yyls = yyls1;
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyexhaustedlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyexhaustedlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ yytype_int16 *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyexhaustedlab;
+ YYSTACK_RELOCATE (yyss_alloc, yyss);
+ YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+ YYSTACK_RELOCATE (yyls_alloc, yyls);
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+ yylsp = yyls + yysize - 1;
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ if (yystate == YYFINAL)
+ YYACCEPT;
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+ /* Do appropriate processing given the current state. Read a
+ lookahead token if we need one and don't already have one. */
+
+ /* First try to decide what to do without reference to lookahead token. */
+ yyn = yypact[yystate];
+ if (yypact_value_is_default (yyn))
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = yylex ();
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yytable_value_is_error (yyn))
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ /* Shift the lookahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+ /* Discard the shifted token. */
+ yychar = YYEMPTY;
+
+ yystate = yyn;
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ *++yyvsp = yylval;
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+ *++yylsp = yylloc;
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ '$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+ /* Default location. */
+ YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 3:
+#line 379 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Lines: Line number " << dec << yylineno << "." << endl;)
+ /* Re-randomize objects we parse into: */
+ expect = expect_info();
+ set_data = set_data_info();
+ parsed_asset = asset_name_id_info();
+ policy_info = key_policy_info();
+ }
+#line 1917 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 4:
+#line 390 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Purpose line: " << flush;)
+ set_purp_str (yytext, rsrc);
+ IVM(cout << rsrc->test_purpose << endl;)
+ /* TODO: Is there much/any value in turning this back on? The
+ constructor clear()s them out, and run-time errors observed
+ under Visual Studio...
+ Just a precaution to make sure that these vectors start out empty.
+ Should inherently be, but purpose is typically specified first:
+ parsed_asset.asset_id_n_vector.clear();
+ parsed_asset.asset_name_vector.clear(); */
+ /* Re-randomize or re-initialize objects we parse into: */
+ purpose_defined = true;
+ expect = expect_info();
+ set_data = set_data_info();
+ parsed_asset = asset_name_id_info();
+ policy_info = key_policy_info();
+ target_barrier = "";
+ }
+#line 1941 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 5:
+#line 409 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ /* 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, rsrc
+ );
+ /* 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, policy_info,
+ print_data, hash_data, asset_name, assign_data_var, parsed_asset,
+ yes_create_call, /* did not create call nor asset earlier */
+ yes_create_asset,
+ dont_fill_in_template, /* but did fill it all in before */
+ 0
+ );
+ k++;
+ for (add_expect = 0; add_expect < rsrc->calls.size(); ++add_expect) {
+ if (!(rsrc->calls[add_expect]->exp_data.expected_results_saved)) {
+ templateLin->expect.copy_expect_to_call (rsrc->calls[add_expect]);
+ templateLin->expect.expected_results_saved = true;
+ }
+ }
+ }
+ templateLin->asset_info.asset_id_n_vector.clear();
+ templateLin->asset_info.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;)
+ }
+#line 1988 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 6:
+#line 451 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Command with no expect: \"" << flush;)
+ if (!purpose_defined) {
+ cerr << endl << endl
+ << "Error: Please begin your test with the \"purpose\" "
+ << "directive. \n For example, "
+ << "\"purpose to exercise crypto and SST...\"" << endl;
+ exit (1024);
+ }
+ if (nesting_level == 0) { /* if laying down the code now... */
+ for (add_expect = 0; add_expect < rsrc->calls.size(); ++add_expect) {
+ if (!(rsrc->calls[add_expect]->exp_data.expected_results_saved)) {
+ templateLin->expect.copy_expect_to_call (rsrc->calls[add_expect]);
+ templateLin->expect.expected_results_saved = true;
+ }
+ }
+ 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;)
+ }
+#line 2017 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 7:
+#line 475 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ /* (This is the same as for command SEMICOLON, other than the IVM.) */
+ IVM(cout << "Command with expect: \"" << flush;)
+ if (!purpose_defined) {
+ cerr << endl << endl
+ << "Error: Please begin your test with the \"purpose\" "
+ << "directive. \n For example, "
+ << "\"purpose to exercise crypto and SST...\"" << endl;
+ exit (1024);
+ }
+ if (nesting_level == 0) {
+ for (add_expect = 0; add_expect < rsrc->calls.size(); ++add_expect) {
+ if (!(rsrc->calls[add_expect]->exp_data.expected_results_saved)) {
+ templateLin->expect.copy_expect_to_call (rsrc->calls[add_expect]);
+ templateLin->expect.expected_results_saved = true;
+ }
+ }
+ delete templateLin;
+ } else {
+ template_block_vector.push_back (templateLin);
+ }
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 2045 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 8:
+#line 501 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Set command: \"" << yytext << "\"" << endl;)
+ }
+#line 2053 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 9:
+#line 504 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Remove command: \"" << yytext << "\"" << endl;)
+ }
+#line 2061 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 10:
+#line 507 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Read command: \"" << yytext << "\"" << endl;)
+ }
+#line 2069 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 11:
+#line 510 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Security command: \"" << yytext << "\"" << endl;)
+ }
+#line 2077 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 12:
+#line 513 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Done command: \"" << yytext << "\"" << endl;)
+ }
+#line 2085 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 13:
+#line 519 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Expect pass clause: \"" << flush;)
+ templateLin->expect.set_pf_pass();
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 2095 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 14:
+#line 524 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Expect fail clause: \"" << flush;)
+ templateLin->expect.set_pf_fail();
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 2105 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 15:
+#line 529 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Expect nothing clause: \"" << flush;)
+ templateLin->expect.set_pf_nothing();
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 2115 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 16:
+#line 534 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Expect error clause: \"" << flush;)
+ templateLin->expect.set_pf_error (identifier);
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 2125 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 17:
+#line 543 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Set SST command: \"" << yytext << "\"" << endl;)
+ templateLin = new set_sst_template_line (rsrc);
+ interpret_template_line (
+ templateLin, rsrc, set_data, random_asset,
+ assign_data_var_specified, expect, policy_info,
+ print_data, hash_data, asset_name, assign_data_var, parsed_asset,
+ nesting_level == 0 /* create call unless inside {} */,
+ nesting_level == 0 /* similarly, create asset unless inside {} */,
+ yes_fill_in_template, 0
+ );
+ }
+#line 2142 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 18:
+#line 555 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Set key command: \"" << yytext << "\"" << endl;)
+ templateLin = new set_key_template_line (rsrc);
+ target_barrier = policy_info.asset_2_name; /* policy */
+ interpret_template_line (
+ templateLin, rsrc, set_data, random_asset,
+ assign_data_var_specified, expect, policy_info,
+ print_data, hash_data, asset_name, assign_data_var, parsed_asset,
+ nesting_level == 0 /* create call unless inside {} */,
+ nesting_level == 0 /* similarly, create asset unless inside {} */,
+ yes_fill_in_template, 0
+ );
+ }
+#line 2160 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 19:
+#line 568 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Set policy command: \"" << yytext << "\"" << endl;;)
+ templateLin = new set_policy_template_line (rsrc);
+ interpret_template_line (
+ templateLin, rsrc, set_data, random_asset,
+ assign_data_var_specified, expect, policy_info,
+ print_data, hash_data, asset_name, assign_data_var, parsed_asset,
+ nesting_level == 0 /* create call unless inside {} */,
+ nesting_level == 0 /* similarly, create asset unless inside {} */,
+ yes_fill_in_template, 0
+ );
+ }
+#line 2177 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 20:
+#line 583 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Read SST command: \"" << yytext << "\"" << endl;;)
+ templateLin = new read_sst_template_line (rsrc);
+ interpret_template_line (
+ templateLin, rsrc, set_data, random_asset,
+ assign_data_var_specified, expect, policy_info,
+ print_data, hash_data, asset_name, assign_data_var, parsed_asset,
+ nesting_level == 0 /* create call unless inside {} */,
+ dont_create_asset /* if no such asset exists, fail the call */,
+ yes_fill_in_template, 0
+ );
+ }
+#line 2194 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 21:
+#line 595 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Read key command: \"" << yytext << "\"" << endl;;)
+ templateLin = new read_key_template_line (rsrc);
+ interpret_template_line (
+ templateLin, rsrc, set_data, random_asset,
+ assign_data_var_specified, expect, policy_info,
+ print_data, hash_data, asset_name, assign_data_var, parsed_asset,
+ nesting_level == 0 /* create call unless inside {} */,
+ dont_create_asset /* if no such asset exists, fail the call */,
+ yes_fill_in_template, 0
+ );
+ }
+#line 2211 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 22:
+#line 607 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Read policy command: \"" << yytext << "\"" << endl;;)
+ templateLin = new read_policy_template_line (rsrc);
+ interpret_template_line (
+ templateLin, rsrc, set_data, random_asset,
+ assign_data_var_specified, expect, policy_info,
+ print_data, hash_data, asset_name, assign_data_var, parsed_asset,
+ nesting_level == 0 /* create call unless inside {} */,
+ dont_create_asset /* if no such asset exists, fail the call */,
+ yes_fill_in_template, 0
+ );
+ }
+#line 2228 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 23:
+#line 622 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Remove SST command: \"" << yytext << "\"" << endl;;)
+ templateLin = new remove_sst_template_line (rsrc);
+ interpret_template_line (
+ templateLin, rsrc, set_data, random_asset,
+ assign_data_var_specified, expect, policy_info,
+ print_data, hash_data, asset_name, assign_data_var, parsed_asset,
+ nesting_level == 0 /* create call unless inside {} */,
+ dont_create_asset /* don't create an asset being deleted */,
+ yes_fill_in_template, 0
+ );
+ }
+#line 2245 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 24:
+#line 634 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Remove key command: \"" << yytext << "\"" << endl;;)
+ templateLin = new remove_key_template_line (rsrc);
+ templateLin->asset_info.set_name (asset_name); // set in key_asset_name, below
+ interpret_template_line (
+ templateLin, rsrc, set_data, random_asset,
+ assign_data_var_specified, expect, policy_info,
+ print_data, hash_data, asset_name, assign_data_var, parsed_asset,
+ nesting_level == 0 /* create call unless inside {} */,
+ dont_create_asset /* don't create an asset being deleted */,
+ yes_fill_in_template, 0
+ );
+ }
+#line 2263 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 25:
+#line 649 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ /* TODO: This needs to allow not only SST assets, but mix and match with others
+ (keys especially) as well. */
+ IVM(cout << "Secure hash command: \"" << yytext << "\"" << endl;)
+ templateLin = new security_hash_template_line (rsrc);
+ templateLin->asset_info.set_name (asset_name);
+ templateLin->assign_data_var_specified = assign_data_var_specified;
+ templateLin->assign_data_var.assign (assign_data_var);
+ templateLin->expect = expect;
+ 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 : parsed_asset.asset_name_vector) {
+ /* Also copy into template line object's local vector: */
+ templateLin->asset_info.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 );
+ parsed_asset.asset_name_vector.clear();
+
+
+ }
+#line 2296 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 26:
+#line 679 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ if (nesting_level != 0) {
+ cerr << "\n\"done\" only available at outer-most { } nesting level."
+ << endl;
+ exit (702);
+ } else {
+ YYACCEPT;
+ }
+ }
+#line 2310 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 27:
+#line 691 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Create from literal data: \"" << flush;)
+ set_data.random_data = false;
+ set_data.string_specified = true;
+ 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;)
+ }
+#line 2325 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 28:
+#line 701 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ { /* TF-Fuzz supplies random data */
+ IVM(cout << "Create from random data" << endl;)
+ set_data.randomize();
+ literal.assign (set_data.get()); /* just in case something uses literal */
+ set_data.random_data = true;
+ set_data.string_specified = false;
+ }
+#line 2337 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 30:
+#line 713 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "SST-create from random data (no 'data *')" << endl;)
+ set_data.randomize();
+ literal.assign (set_data.get()); /* just in case something uses literal */
+ }
+#line 2347 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 31:
+#line 718 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ { /* set from variable */
+ IVM(cout << "SST-set set from variable: \"" << flush;)
+ assign_data_var.assign (identifier);
+ assign_data_var_specified = true;
+ expect.data_specified = false;
+ expect.data_var_specified = false;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 2360 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 32:
+#line 726 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ 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 if so, write code to write code to
+ set data appropriately from the file. */
+ }
+#line 2372 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 34:
+#line 737 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "SST creation flags" << endl;)
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 2381 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 36:
+#line 745 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "SST creation flag" << endl;)
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 2390 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 41:
+#line 753 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ set_data.flags_string = "PSA_STORAGE_FLAG_NONE";
+ /* TODO: grab from boilerplate */
+ IVM(cout << "SST no storage flag: " << yytext << "\"" << endl;)
+ }
+#line 2400 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 42:
+#line 760 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ set_data.flags_string = "PSA_STORAGE_FLAG_WRITE_ONCE";
+ /* TODO: grab from boilerplate */
+ IVM(cout << "SST write-once flag: " << yytext << "\"" << endl;)
+ }
+#line 2410 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 43:
+#line 767 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ set_data.flags_string = "PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION";
+ /* TODO: grab from boilerplate */
+ IVM(cout << "SST no-replay-protection flag: "
+ << yytext << "\"" << endl;)
+ }
+#line 2421 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 44:
+#line 775 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ set_data.flags_string = "PSA_STORAGE_FLAG_NO_CONFIDENTIALITY";
+ /* TODO: grab from boilerplate */
+ IVM(cout << "SST no-confidentiality flag: " << yytext
+ << "\"" << endl;)
+ }
+#line 2432 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 45:
+#line 784 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "SST-data offset: \"" << flush;)
+ set_data.data_offset = atol(yytext);
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 2442 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 46:
+#line 793 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "SST-read arguments: " << yytext << "\"" << endl;)
+ }
+#line 2450 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 47:
+#line 799 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ { /* dump to variable */
+ IVM(cout << "Read dump to variable: \"" << flush;)
+ assign_data_var.assign (identifier);
+ assign_data_var_specified = true;
+ expect.data_specified = false;
+ expect.data_var_specified = false;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 2463 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 48:
+#line 807 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ { /* check against variable */
+ IVM(cout << "Read check against variable: \""
+ << yytext << "\"" << endl;)
+ set_data.set (literal);
+ assign_data_var_specified = false;
+ expect.data_specified = false;
+ expect.data_var_specified = true;
+ expect.data_var = identifier;
+ }
+#line 2477 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 49:
+#line 816 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ { /* check against literal */
+ IVM(cout << "Read check against literal: " << flush;)
+ 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; /* don't read variable */
+ expect.data_specified = true; /* check against literal data */
+ expect.data_var_specified = false; /* don't check against variable */
+ IVM(cout << yytext << endl;)
+ }
+#line 2492 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 50:
+#line 826 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ { /* print out content in test log */
+ IVM(cout << "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;)
+ }
+#line 2509 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 51:
+#line 838 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ { /* hash the data and save for later comparison */
+ IVM(cout << "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;)
+ }
+#line 2527 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 52:
+#line 851 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ { /* dump to file */
+ IVM(cout << "Read dump to file: \""
+ << yytext << "\"" << endl;)
+ set_data.literal_data_not_file = set_data.random_data = false;
+ }
+#line 2537 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 54:
+#line 860 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "SST data offset" << endl;)
+ set_data.data_offset = atol(yytext);
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 2547 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 56:
+#line 868 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "SST-remove arguments: \""
+ << yytext << "\"" << endl;)
+ }
+#line 2556 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 57:
+#line 875 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "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 randomly choose existing asset */
+ parsed_asset.id_n_not_name = false;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 2569 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 58:
+#line 883 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Asset random identifier: \"" << flush;)
+ random_name = true;
+ rand_data_length = 4 + (rand() % 5);
+ gib.word (false, gib_buff, gib_buff + rand_data_length - 1);
+ aid.assign (gib_buff);
+ parsed_asset.asset_name_vector.push_back (aid);
+ random_asset = psa_asset_usage::all; /* don't randomly choose existing asset */
+ parsed_asset.id_n_not_name = false;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 2585 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 59:
+#line 896 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Single existing asset by name: \"" << flush;)
+ random_name = false;
+ policy_info.asset_3_name.assign (identifier);
+ random_asset = psa_asset_usage::all; /* don't randomly choose existing asset */
+ parsed_asset.id_n_not_name = false;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 2598 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 61:
+#line 908 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Asset random active: \"" << flush;)
+ random_asset = psa_asset_usage::active;
+ parsed_asset.id_n_not_name = false;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 2609 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 62:
+#line 914 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Asset random deleted: \"" << flush;)
+ random_asset = psa_asset_usage::deleted;
+ parsed_asset.id_n_not_name = false;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 2620 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 64:
+#line 924 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "SST-asset UID list: \"" << flush;)
+ random_name = false;
+ random_asset = psa_asset_usage::all; /* don't randomly choose existing asset */
+ parsed_asset.id_n_not_name = true;
+ parsed_asset.id_n_specified = true;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 2633 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 65:
+#line 932 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "SST-asset random UID: \"" << flush;)
+ parsed_asset.id_n_not_name = true;
+ random_name = false;
+ nid = 100 + (rand() % 10000);
+ parsed_asset.asset_id_n_vector.push_back (nid);
+ random_asset = psa_asset_usage::all; /* don't randomly choose existing asset */
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 2647 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 66:
+#line 944 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "SST-asset-create file path: \"" << flush;)
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 2656 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 67:
+#line 951 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Read-arguments variable name: \"" << flush;)
+ var_name = yytext;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 2666 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 68:
+#line 959 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "SST-asset dump-file path: \"" << flush;)
+ set_data.file_path = yytext;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 2676 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 69:
+#line 967 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Key size: \"" << flush;)
+ policy_info.n_bits = atol(yytext);
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 2686 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 72:
+#line 978 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Key-policy usages at line number " << dec << yylineno
+ << "." << endl;)
+ }
+#line 2695 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 73:
+#line 984 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ policy_info.exportable = true;
+ IVM(cout << "Exportable key true: " << yytext << "\"" << endl;)
+ }
+#line 2704 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 74:
+#line 990 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ policy_info.exportable = false;
+ IVM(cout << "Non-exportable key: " << yytext << "\"" << endl;)
+ }
+#line 2713 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 75:
+#line 996 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ policy_info.copyable = true;
+ IVM(cout << "Copyable key true: " << yytext << "\"" << endl;)
+ }
+#line 2722 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 76:
+#line 1002 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ policy_info.copyable = false;
+ IVM(cout << "Non-copyable key: " << yytext << "\"" << endl;)
+ }
+#line 2731 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 77:
+#line 1008 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ policy_info.can_encrypt = true;
+ IVM(cout << "Encryption key true: " << yytext << "\"" << endl;)
+ }
+#line 2740 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 78:
+#line 1014 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ policy_info.can_encrypt = false;
+ IVM(cout << "Non-encryption key: " << yytext << "\"" << endl;)
+ }
+#line 2749 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 79:
+#line 1020 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ policy_info.can_decrypt = true;
+ IVM(cout << "Decryption key true: " << yytext << "\"" << endl;)
+ }
+#line 2758 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 80:
+#line 1026 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ policy_info.can_decrypt = false;
+ IVM(cout << "Non-decryption key: " << yytext << "\"" << endl;)
+ }
+#line 2767 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 81:
+#line 1032 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ policy_info.can_sign = true;
+ IVM(cout << "Signing key true: " << yytext << "\"" << endl;)
+ }
+#line 2776 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 82:
+#line 1038 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ policy_info.can_sign = false;
+ IVM(cout << "Non-signing key: " << yytext << "\"" << endl;)
+ }
+#line 2785 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 83:
+#line 1044 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ policy_info.can_verify = true;
+ IVM(cout << "Verify key true: " << yytext << "\"" << endl;)
+ }
+#line 2794 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 84:
+#line 1050 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ policy_info.can_verify = false;
+ IVM(cout << "Non-verify key: " << yytext << "\"" << endl;)
+ }
+#line 2803 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 85:
+#line 1056 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ policy_info.derivable = true;
+ IVM(cout << "Derivable key true: " << yytext << "\"" << endl;)
+ }
+#line 2812 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 86:
+#line 1062 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ policy_info.derivable = false;
+ IVM(cout << "Non-derivable key: " << yytext << "\"" << endl;)
+ }
+#line 2821 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 87:
+#line 1068 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ policy_info.persistent = true;
+ IVM(cout << "Persistent key: " << yytext << "\"" << endl;)
+ }
+#line 2830 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 88:
+#line 1074 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ policy_info.persistent = false;
+ IVM(cout << "Volatile key: " << yytext << "\"" << endl;)
+ }
+#line 2839 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 105:
+#line 1083 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Policy usage: " << yytext << "\"" << endl;)
+ }
+#line 2847 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 106:
+#line 1089 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ // Change type identifier, e.g., from "raw_data" to PSA_KEY_TYPE_RAW_DATA:
+ identifier = formalize (identifier, "PSA_KEY_TYPE_");
+ policy_info.key_type = identifier;
+ IVM(cout << "Policy type: \""
+ << policy_info.key_type << "\"" << endl;)
+ }
+#line 2859 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 107:
+#line 1098 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ // Change type identifier, e.g., from "sha_256" to PSA_ALG_SHA_256:
+ identifier = formalize (identifier, "PSA_ALG_");
+ policy_info.key_algorithm = identifier;
+ IVM(cout << "Policy algorithm: \""
+ << policy_info.key_algorithm << "\"" << endl;)
+ }
+#line 2871 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 109:
+#line 1108 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Key-policy specs at line number " << dec << yylineno
+ << "." << endl;)
+ }
+#line 2880 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 114:
+#line 1118 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "policy-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 randomly choose existing asset */
+ parsed_asset.id_n_not_name = false;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 2893 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 115:
+#line 1126 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "policy-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);
+ parsed_asset.asset_name_vector.push_back (aid);
+ random_asset = psa_asset_usage::all; /* don't randomly choose existing asset */
+ parsed_asset.id_n_not_name = false;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 2909 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 116:
+#line 1140 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "policy-asset identifier list: \"" << flush;)
+ random_name = false;
+ policy_info.get_policy_from_key = false;
+ asset_name.assign (identifier); /* TODO: Not sure this ultimately has any effect... */
+ parsed_asset.asset_name_vector.push_back (identifier);
+ random_asset = psa_asset_usage::all; /* don't randomly choose existing asset */
+ parsed_asset.id_n_not_name = false;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 2924 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 117:
+#line 1150 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "policy-asset random active: \"" << flush;)
+ policy_info.get_policy_from_key = false;
+ random_asset = psa_asset_usage::active;
+ parsed_asset.id_n_not_name = false;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 2936 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 118:
+#line 1157 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "policy-asset random deleted: \"" << flush;)
+ policy_info.get_policy_from_key = false;
+ random_asset = psa_asset_usage::deleted;
+ parsed_asset.id_n_not_name = false;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 2948 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 119:
+#line 1164 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "policy-asset specified by key: \"" << flush;)
+ policy_info.get_policy_from_key = true;
+ random_name = false;
+ asset_name.assign (identifier); /* ask this key what it's policy is */
+ random_asset = psa_asset_usage::all; /* don't randomly choose existing asset */
+ parsed_asset.id_n_not_name = false;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 2962 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 120:
+#line 1176 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Policy-create arguments: \"" << yytext << "\"" << endl;)
+ }
+#line 2970 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 121:
+#line 1182 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Policy-read arguments: " << yytext << "\"" << endl;)
+ }
+#line 2978 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 123:
+#line 1189 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Key-set sources at Line number "
+ << yytext << "\"" << endl;)
+ }
+#line 2987 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 124:
+#line 1196 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Key-set sources, literal or random data: "
+ << yytext << "\"" << endl;)
+ }
+#line 2996 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 125:
+#line 1200 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Key-set sources, explicitly-specified policy name: "
+ << flush;)
+ policy_info.asset_2_name = identifier; /* policy */
+ /* Make note that key data (key material) was not specified: */
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 3008 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 127:
+#line 1211 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Key data, literal or random data: "
+ << yytext << "\"" << endl;)
+ }
+#line 3017 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 128:
+#line 1218 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Key-create from data, policy, or nothing (default): \""
+ << yytext << "\"" << endl;)
+ policy_info.copy_key = false;
+ policy_info.implicit_policy = false;
+ }
+#line 3028 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 129:
+#line 1224 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Key-copy from other key: \"" << flush;)
+ policy_info.asset_2_name = identifier; /* policy */
+ policy_info.copy_key = true;
+ policy_info.implicit_policy = false;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 3040 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 130:
+#line 1231 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Key-create directly specifying policy attributes (implicit policy): \""
+ << yytext << "\"" << endl;)
+ policy_info.copy_key = false;
+ policy_info.implicit_policy = true;
+ cerr << "\nError: Defining keys with implicit policies is not yet implemented."
+ << endl;
+ exit (772);
+ }
+#line 3054 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 131:
+#line 1243 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Key-remove arguments: \""
+ << yytext << "\"" << endl;)
+ }
+#line 3063 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 132:
+#line 1250 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Key dump: \"" << yytext << "\"" << endl;)
+ }
+#line 3071 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 133:
+#line 1257 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ 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;)
+ }
+#line 3087 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 134:
+#line 1268 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ 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;)
+ }
+#line 3098 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 135:
+#line 1274 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ 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;)
+ }
+#line 3114 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 136:
+#line 1288 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Block content: \"" << yytext << "\"" << endl;)
+ }
+#line 3122 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 137:
+#line 1291 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Single-line would-be-block content: \"" << flush;)
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 3131 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 138:
+#line 1298 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Open brace: \"" << flush;)
+ template_block_vector.clear(); // clean slate of template lines
+ nesting_level = 1;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 3142 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 139:
+#line 1307 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Close brace: " << flush;)
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 3151 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 143:
+#line 1324 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "ASSET_NUMBER: \"" << flush;)
+ nid = atol(yytext);
+ parsed_asset.asset_id_n_vector.push_back (nid);
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 3162 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 147:
+#line 1344 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "ASSET_IDENTIFIER: \"" << flush;)
+ aid = identifier = yytext;
+ parsed_asset.asset_name_vector.push_back (aid);
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 3173 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 148:
+#line 1353 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "IDENTIFIER: \"" << flush;)
+ identifier = yytext;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 3183 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 149:
+#line 1361 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "FILE_PATH: \"" << flush;)
+ set_data.file_path = yytext;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 3193 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 150:
+#line 1371 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ 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;)
+ }
+#line 3204 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 151:
+#line 1380 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Least number of random template lines: \"" << flush;)
+ low_nmbr_lines = number;
+ IVM(cout << number << "\"" << endl;)
+ }
+#line 3214 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 152:
+#line 1388 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "Most number of random template lines: \"" << flush;)
+ high_nmbr_lines = number;
+ ++nesting_level;
+ IVM(cout << number << "\"" << endl;)
+ }
+#line 3225 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 153:
+#line 1399 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "NUMBER: \"" << flush;)
+ number = atol(yytext);
+ IVM(cout << yytext << "\"" << endl;)
+ }
+#line 3235 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 154:
+#line 1407 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "LITERAL string: " << flush;)
+ literal = yytext;
+ literal_is_string = true;
+ IVM(cout << yytext << endl;)
+ }
+#line 3246 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 155:
+#line 1413 "parser/tf_fuzz_grammar.y" /* yacc.c:1646 */
+ {
+ IVM(cout << "LITERAL hex-value list: " << flush;)
+ literal = yytext;
+ literal_is_string = false;
+ IVM(cout << yytext << endl;)
+ }
+#line 3257 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ break;
+
+
+#line 3261 "parser/tf_fuzz_grammar.tab.cpp" /* yacc.c:1646 */
+ default: break;
+ }
+ /* User semantic actions sometimes alter yychar, and that requires
+ that yytoken be updated with the new translation. We take the
+ approach of translating immediately before every use of yytoken.
+ One alternative is translating here after every semantic action,
+ but that translation would be missed if the semantic action invokes
+ YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
+ if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an
+ incorrect destructor might then be invoked immediately. In the
+ case of YYERROR or YYBACKUP, subsequent parser actions might lead
+ to an incorrect destructor call or verbose syntax error message
+ before the lookahead is translated. */
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+ *++yylsp = yyloc;
+
+ /* Now 'shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*--------------------------------------.
+| yyerrlab -- here on detecting error. |
+`--------------------------------------*/
+yyerrlab:
+ /* Make sure we have latest lookahead translation. See comments at
+ user semantic actions for why this is necessary. */
+ yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
+
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if ! YYERROR_VERBOSE
+ yyerror (rsrc, YY_("syntax error"));
+#else
+# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
+ yyssp, yytoken)
+ {
+ char const *yymsgp = YY_("syntax error");
+ int yysyntax_error_status;
+ yysyntax_error_status = YYSYNTAX_ERROR;
+ if (yysyntax_error_status == 0)
+ yymsgp = yymsg;
+ else if (yysyntax_error_status == 1)
+ {
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
+ if (!yymsg)
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ yysyntax_error_status = 2;
+ }
+ else
+ {
+ yysyntax_error_status = YYSYNTAX_ERROR;
+ yymsgp = yymsg;
+ }
+ }
+ yyerror (rsrc, yymsgp);
+ if (yysyntax_error_status == 2)
+ goto yyexhaustedlab;
+ }
+# undef YYSYNTAX_ERROR
+#endif
+ }
+
+ yyerror_range[1] = yylloc;
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse lookahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
+ else
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval, &yylloc, rsrc);
+ yychar = YYEMPTY;
+ }
+ }
+
+ /* Else will try to reuse lookahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+
+ /* Pacify compilers like GCC when the user code never invokes
+ YYERROR and the label yyerrorlab therefore never appears in user
+ code. */
+ if (/*CONSTCOND*/ 0)
+ goto yyerrorlab;
+
+ yyerror_range[1] = yylsp[1-yylen];
+ /* Do not reclaim the symbols of the rule whose action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (!yypact_value_is_default (yyn))
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+ yyerror_range[1] = *yylsp;
+ yydestruct ("Error: popping",
+ yystos[yystate], yyvsp, yylsp, rsrc);
+ YYPOPSTACK (1);
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ *++yyvsp = yylval;
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+ yyerror_range[2] = yylloc;
+ /* Using YYLLOC is tempting, but would change the location of
+ the lookahead. YYLOC is available though. */
+ YYLLOC_DEFAULT (yyloc, yyerror_range, 2);
+ *++yylsp = yyloc;
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#if !defined yyoverflow || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here. |
+`-------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (rsrc, YY_("memory exhausted"));
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+ if (yychar != YYEMPTY)
+ {
+ /* Make sure we have latest lookahead translation. See comments at
+ user semantic actions for why this is necessary. */
+ yytoken = YYTRANSLATE (yychar);
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval, &yylloc, rsrc);
+ }
+ /* Do not reclaim the symbols of the rule whose action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+ yystos[*yyssp], yyvsp, yylsp, rsrc);
+ YYPOPSTACK (1);
+ }
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+#endif
+ return yyresult;
+}
+#line 1422 "parser/tf_fuzz_grammar.y" /* yacc.c:1906 */
+
+
diff --git a/tf_fuzz/parser/tf_fuzz_grammar.tab.hpp b/tf_fuzz/parser/tf_fuzz_grammar.tab.hpp
new file mode 100644
index 0000000..a9a9488
--- /dev/null
+++ b/tf_fuzz/parser/tf_fuzz_grammar.tab.hpp
@@ -0,0 +1,152 @@
+/* A Bison parser, made by GNU Bison 3.0.4. */
+
+/* Bison interface for Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+#ifndef YY_YY_PARSER_TF_FUZZ_GRAMMAR_TAB_HPP_INCLUDED
+# define YY_YY_PARSER_TF_FUZZ_GRAMMAR_TAB_HPP_INCLUDED
+/* Debug traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int yydebug;
+#endif
+
+/* Token type. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ enum yytokentype
+ {
+ PURPOSE = 258,
+ RAW_TEXT = 259,
+ SET = 260,
+ READ = 261,
+ REMOVE = 262,
+ SECURE = 263,
+ DONE = 264,
+ SST = 265,
+ KEY = 266,
+ POLICY = 267,
+ NAME = 268,
+ UID = 269,
+ STAR = 270,
+ ACTIVE = 271,
+ DELETED = 272,
+ EQUAL = 273,
+ DATA = 274,
+ DFNAME = 275,
+ FLAG = 276,
+ NONE = 277,
+ WRITE_ONCE = 278,
+ NO_RP = 279,
+ NO_CONF = 280,
+ OFFSET = 281,
+ CHECK = 282,
+ VAR = 283,
+ HASH = 284,
+ NEQ = 285,
+ PRINT = 286,
+ EXPECT = 287,
+ PASS = 288,
+ FAIL = 289,
+ NOTHING = 290,
+ ERROR = 291,
+ IDENTIFIER_TOK = 292,
+ LITERAL_TOK = 293,
+ HEX_LIST = 294,
+ FILE_PATH_TOK = 295,
+ NUMBER_TOK = 296,
+ SEMICOLON = 297,
+ SHUFFLE = 298,
+ TO = 299,
+ OF = 300,
+ OPEN_BRACE = 301,
+ CLOSE_BRACE = 302,
+ ATTR = 303,
+ TYPE = 304,
+ ALG = 305,
+ EXPORT = 306,
+ COPY = 307,
+ ENCRYPT = 308,
+ DECRYPT = 309,
+ SIGN = 310,
+ VERIFY = 311,
+ DERIVE = 312,
+ NOEXPORT = 313,
+ NOCOPY = 314,
+ NOENCRYPT = 315,
+ NODECRYPT = 316,
+ NOSIGN = 317,
+ NOVERIFY = 318,
+ NODERIVE = 319,
+ PERSISTENT = 320,
+ VOLATILE = 321,
+ FROM = 322,
+ WITH = 323
+ };
+#endif
+
+/* Value type. */
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+
+union YYSTYPE
+{
+#line 353 "parser/tf_fuzz_grammar.y" /* yacc.c:1909 */
+int valueN; int tokenN; char *str;
+
+#line 126 "parser/tf_fuzz_grammar.tab.hpp" /* yacc.c:1909 */
+};
+
+typedef union YYSTYPE YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+/* Location type. */
+#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
+typedef struct YYLTYPE YYLTYPE;
+struct YYLTYPE
+{
+ int first_line;
+ int first_column;
+ int last_line;
+ int last_column;
+};
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+#endif
+
+
+extern YYSTYPE yylval;
+extern YYLTYPE yylloc;
+int yyparse (tf_fuzz_info *rsrc);
+
+#endif /* !YY_YY_PARSER_TF_FUZZ_GRAMMAR_TAB_HPP_INCLUDED */
diff --git a/tf_fuzz/parser/tf_fuzz_grammar.tab.o b/tf_fuzz/parser/tf_fuzz_grammar.tab.o
new file mode 100644
index 0000000..5954ef6
--- /dev/null
+++ b/tf_fuzz/parser/tf_fuzz_grammar.tab.o
Binary files differ
diff --git a/tf_fuzz/parser/tf_fuzz_grammar.y b/tf_fuzz/parser/tf_fuzz_grammar.y
new file mode 100644
index 0000000..17c31b4
--- /dev/null
+++ b/tf_fuzz/parser/tf_fuzz_grammar.y
@@ -0,0 +1,1423 @@
+/*
+ * 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 *);
+ /* Sends the yyparse() argument to yyerror(), probably, to print incorrect
+ text it parsed. */
+
+/* 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 is used for now, but this is a good outline of
+ of the template_line class hierarchy. */
+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 only just to
+ show that 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;
+ init_policy_call *iniPolCal = nullptr;
+ reset_policy_call *resPolCal = nullptr;
+ add_policy_usage_call *addPolUsaCal = nullptr;
+ set_policy_lifetime_call *setPolLifCal = nullptr;
+ set_policy_type_call *setPolTypCal = nullptr;
+ set_policy_algorithm_call *setPolAlgCal = nullptr;
+ set_policy_usage_call *setPolUsaCal = nullptr;
+ get_policy_lifetime_call *getPolLifCal = nullptr;
+ get_policy_type_call *getPolTypCal = nullptr;
+ get_policy_algorithm_call *getPolAlgCal = nullptr;
+ get_policy_usage_call *getPolUsaCal = nullptr;
+ get_policy_size_call *getPolSizCal = nullptr;
+ get_key_policy_call *getKeyPolCal = nullptr;
+ key_call *keyCal = nullptr;
+ generate_key_call *genKeyCal = nullptr;
+ create_key_call *creKeyCal = nullptr;
+ copy_key_call *copKeyCal = nullptr;
+ read_key_data_call *reaKeyDatCal = nullptr;
+ remove_key_call *remKeyCal = 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: */
+bool purpose_defined = false;
+psa_asset_usage random_asset = psa_asset_usage::all;
+ /* to 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 parsed_asset; /* everything about identifying assets */
+string target_barrier = ""; /* asset to set and search barrier when re-ordering PSA calls */
+key_policy_info policy_info; /* everything about key policies */
+bool assign_data_var_specified = false;
+string assign_data_var;
+bool print_data = false; /* true to just print asset data to the test log */
+bool hash_data = false; /* true to just print asset data to the test log */
+bool literal_is_string = true;
+ /* if true, literal value is character-string; if false, is list of hex values */
+
+/* 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 parsed_asset */
+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,
+ must inject those results after parsing the expected results. add_expect is a
+ loop index to track where to add results. */
+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;
+
+using namespace std;
+
+
+void set_purp_str (
+ char *raw_purpose, /* the purpose C string from parser */
+ tf_fuzz_info *rsrc /* test resources containing the actual test-purpose string */
+) {
+ size_t l; /* temporary of size_t type */
+ string purp_str = raw_purpose;
+ 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);
+ l = 0;
+ do { /* escape all " chars (if not already escaped) */
+ l = purp_str.find ("\"", l);
+ if ( l < purp_str.length()) { /* did find a quote character */
+ if ( l == 0 /* it's the first character in the string*/
+ || purp_str[l-1] != '\\' /* or it's not already escaped */
+ ) {
+ purp_str.insert (l, "\\"); /* then escape the " char */
+ l++; /* point l to the " again */
+ }
+ l++; /* point l past the " */
+ }
+ } while (l < purp_str.length());
+ rsrc->test_purpose = purp_str;
+}
+
+/* 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,
+ tf_fuzz_info *rsrc /* test resources containing the actual test-purpose string */
+) {
+ 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);
+ }
+ }
+ IVM(cout << "Order of lines in block: " << flush;
+ for (auto i : block_order) {
+ cout << i << " ";
+ }
+ cout << endl;
+ )
+}
+
+/* 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, key_policy_info &policy_info,
+ bool print_data, bool hash_data, string asset_name, string assign_data_var,
+ asset_name_id_info &asset_info, /* 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 instance >0 */
+) {
+ const bool yes_fill_in_template = true; /* just to improve readability */
+ vector<psa_asset*>::iterator t_psa_asset;
+
+ if (fill_in_template) {
+ /* Set basic parameters from the template line: */
+ templateLin->set_data = set_data;
+ templateLin->expect = expect;
+ templateLin->policy_info = policy_info;
+ templateLin->asset_info.id_n_not_name = asset_info.id_n_not_name;
+ templateLin->asset_info.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->print_data = print_data;
+ templateLin->hash_data = hash_data;
+ templateLin->random_asset = random_asset;
+ if ( set_data.literal_data_not_file && !set_data.random_data
+ && set_data.string_specified) {
+ templateLin->set_data.set (literal_data);
+ }
+ /* Save names or IDs to the template-line tracker: */
+ for (auto id_no : asset_info.asset_id_n_vector) {
+ templateLin->asset_info.asset_id_n_vector.push_back (id_no);
+ }
+ asset_info.asset_id_n_vector.clear();
+ for (auto as_name : asset_info.asset_name_vector) {
+ templateLin->asset_info.asset_name_vector.push_back (as_name);
+ }
+ asset_info.asset_name_vector.clear();
+ }
+
+ /* Random asset choice (e.g., *active) case: */
+ if (templateLin->random_asset != psa_asset_usage::all) {
+ /* Just create the call tracker; random name chosen in simulation stage: */
+ templateLin->setup_call (set_data, templateLin->set_data.random_data,
+ yes_fill_in_template, create_call_bool,
+ templateLin, rsrc );
+ } else if (asset_info.id_n_not_name) {
+ /* Not random asset; asset(s) by ID rather than name. Go through all
+ specified asset IDs: */
+ uint64_t id_no;
+ for (auto id_n : templateLin->asset_info.asset_id_n_vector) {
+ id_no = id_n + (uint64_t) instance * 10000UL;
+ templateLin->asset_info.set_id_n(id_no); /* just a holder */
+ asset_name = templateLin->asset_info.make_id_n_based_name (id_no);
+ templateLin->asset_info.set_calc_name (asset_name);
+ templateLin->expect.data_var = var_name;
+ if (!set_data.literal_data_not_file) {
+ templateLin->set_data.set_file (set_data.file_path);
+ }
+ templateLin->setup_call (set_data, templateLin->set_data.random_data,
+ fill_in_template, create_call_bool,
+ templateLin, rsrc );
+ }
+ } else {
+ /* Not random asset, asset(s) specified by name. Go through all specified
+ asset names: */
+ for (auto as_name : templateLin->asset_info.asset_name_vector) {
+ /* Also copy into template line object's local vector: */
+ if (instance > 0) {
+ templateLin->asset_info.set_name (as_name + "_" + to_string (instance));
+ } else {
+ templateLin->asset_info.set_name (as_name);
+ }
+ /* Give each occurrence a different random ID: */
+ templateLin->asset_info.set_id_n (100 + (rand() % 10000));
+ /* TODO: unlikely, but this *could* alias! */
+ templateLin->setup_call (set_data, templateLin->set_data.random_data,
+ yes_fill_in_template, create_call_bool,
+ templateLin, rsrc );
+ }
+ }
+}
+
+%}
+
+%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> FLAG NONE WRITE_ONCE NO_RP NO_CONF /* SST creation flag keywords */
+%token <tokenN> OFFSET /* offset into an SST asset */
+%token <tokenN> CHECK VAR HASH NEQ PRINT EXPECT PASS FAIL NOTHING ERROR /* expected results */
+%token <str> IDENTIFIER_TOK LITERAL_TOK HEX_LIST 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 */
+%token <tokenN> ATTR TYPE ALG /* "set policy" line portions */
+%token <tokenN> EXPORT COPY ENCRYPT DECRYPT SIGN VERIFY DERIVE /* key-usage keywords */
+%token <tokenN> NOEXPORT NOCOPY NOENCRYPT NODECRYPT NOSIGN NOVERIFY NODERIVE
+%token <tokenN> PERSISTENT VOLATILE /* key lifetime keywords */
+%token <tokenN> FROM /* for copying a key "from" another */
+%token <tokenN> WITH /* for specifying a key without explicitly defining a policy */
+
+%define parse.error verbose
+%locations
+%parse-param {tf_fuzz_info *rsrc}
+
+%%
+
+ /* Top-level syntax: */
+lines:
+ %empty /* nothing */
+ | line lines {
+ IVM(cout << "Lines: Line number " << dec << yylineno << "." << endl;)
+ /* Re-randomize objects we parse into: */
+ expect = expect_info();
+ set_data = set_data_info();
+ parsed_asset = asset_name_id_info();
+ policy_info = key_policy_info();
+ }
+ ;
+
+line:
+ PURPOSE {
+ IVM(cout << "Purpose line: " << flush;)
+ set_purp_str (yytext, rsrc);
+ IVM(cout << rsrc->test_purpose << endl;)
+ /* TODO: Is there much/any value in turning this back on? The
+ constructor clear()s them out, and run-time errors observed
+ under Visual Studio...
+ Just a precaution to make sure that these vectors start out empty.
+ Should inherently be, but purpose is typically specified first:
+ parsed_asset.asset_id_n_vector.clear();
+ parsed_asset.asset_name_vector.clear(); */
+ /* Re-randomize or re-initialize objects we parse into: */
+ purpose_defined = true;
+ expect = expect_info();
+ set_data = set_data_info();
+ parsed_asset = asset_name_id_info();
+ policy_info = key_policy_info();
+ target_barrier = "";
+ }
+ | 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, rsrc
+ );
+ /* 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, policy_info,
+ print_data, hash_data, asset_name, assign_data_var, parsed_asset,
+ yes_create_call, /* did not create call nor asset earlier */
+ yes_create_asset,
+ dont_fill_in_template, /* but did fill it all in before */
+ 0
+ );
+ k++;
+ for (add_expect = 0; add_expect < rsrc->calls.size(); ++add_expect) {
+ if (!(rsrc->calls[add_expect]->exp_data.expected_results_saved)) {
+ templateLin->expect.copy_expect_to_call (rsrc->calls[add_expect]);
+ templateLin->expect.expected_results_saved = true;
+ }
+ }
+ }
+ templateLin->asset_info.asset_id_n_vector.clear();
+ templateLin->asset_info.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 (!purpose_defined) {
+ cerr << endl << endl
+ << "Error: Please begin your test with the \"purpose\" "
+ << "directive. \n For example, "
+ << "\"purpose to exercise crypto and SST...\"" << endl;
+ exit (1024);
+ }
+ if (nesting_level == 0) { /* if laying down the code now... */
+ for (add_expect = 0; add_expect < rsrc->calls.size(); ++add_expect) {
+ if (!(rsrc->calls[add_expect]->exp_data.expected_results_saved)) {
+ templateLin->expect.copy_expect_to_call (rsrc->calls[add_expect]);
+ templateLin->expect.expected_results_saved = true;
+ }
+ }
+ 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 {
+ /* (This is the same as for command SEMICOLON, other than the IVM.) */
+ IVM(cout << "Command with expect: \"" << flush;)
+ if (!purpose_defined) {
+ cerr << endl << endl
+ << "Error: Please begin your test with the \"purpose\" "
+ << "directive. \n For example, "
+ << "\"purpose to exercise crypto and SST...\"" << endl;
+ exit (1024);
+ }
+ if (nesting_level == 0) {
+ for (add_expect = 0; add_expect < rsrc->calls.size(); ++add_expect) {
+ if (!(rsrc->calls[add_expect]->exp_data.expected_results_saved)) {
+ templateLin->expect.copy_expect_to_call (rsrc->calls[add_expect]);
+ templateLin->expect.expected_results_saved = true;
+ }
+ }
+ delete templateLin;
+ } 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 FAIL {
+ IVM(cout << "Expect fail clause: \"" << flush;)
+ templateLin->expect.set_pf_fail();
+ 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 sst_set_base_args sst_set_extended_args {
+ IVM(cout << "Set SST command: \"" << yytext << "\"" << endl;)
+ templateLin = new set_sst_template_line (rsrc);
+ interpret_template_line (
+ templateLin, rsrc, set_data, random_asset,
+ assign_data_var_specified, expect, policy_info,
+ print_data, hash_data, asset_name, assign_data_var, parsed_asset,
+ nesting_level == 0 /* create call unless inside {} */,
+ nesting_level == 0 /* similarly, create asset unless inside {} */,
+ yes_fill_in_template, 0
+ );
+ }
+ | SET KEY key_set_args {
+ IVM(cout << "Set key command: \"" << yytext << "\"" << endl;)
+ templateLin = new set_key_template_line (rsrc);
+ target_barrier = policy_info.asset_2_name; /* policy */
+ interpret_template_line (
+ templateLin, rsrc, set_data, random_asset,
+ assign_data_var_specified, expect, policy_info,
+ print_data, hash_data, asset_name, assign_data_var, parsed_asset,
+ nesting_level == 0 /* create call unless inside {} */,
+ nesting_level == 0 /* similarly, create asset unless inside {} */,
+ yes_fill_in_template, 0
+ );
+ }
+ | SET POLICY policy_set_args {
+ IVM(cout << "Set policy command: \"" << yytext << "\"" << endl;;)
+ templateLin = new set_policy_template_line (rsrc);
+ interpret_template_line (
+ templateLin, rsrc, set_data, random_asset,
+ assign_data_var_specified, expect, policy_info,
+ print_data, hash_data, asset_name, assign_data_var, parsed_asset,
+ nesting_level == 0 /* create call unless inside {} */,
+ nesting_level == 0 /* similarly, create asset unless inside {} */,
+ yes_fill_in_template, 0
+ );
+ }
+ ;
+
+read_command:
+ READ SST sst_read_args {
+ IVM(cout << "Read SST command: \"" << yytext << "\"" << endl;;)
+ templateLin = new read_sst_template_line (rsrc);
+ interpret_template_line (
+ templateLin, rsrc, set_data, random_asset,
+ assign_data_var_specified, expect, policy_info,
+ print_data, hash_data, asset_name, assign_data_var, parsed_asset,
+ nesting_level == 0 /* create call unless inside {} */,
+ dont_create_asset /* if no such asset exists, fail the call */,
+ yes_fill_in_template, 0
+ );
+ }
+ | READ KEY key_read_args {
+ IVM(cout << "Read key command: \"" << yytext << "\"" << endl;;)
+ templateLin = new read_key_template_line (rsrc);
+ interpret_template_line (
+ templateLin, rsrc, set_data, random_asset,
+ assign_data_var_specified, expect, policy_info,
+ print_data, hash_data, asset_name, assign_data_var, parsed_asset,
+ nesting_level == 0 /* create call unless inside {} */,
+ dont_create_asset /* if no such asset exists, fail the call */,
+ yes_fill_in_template, 0
+ );
+ }
+ | READ POLICY policy_read_args {
+ IVM(cout << "Read policy command: \"" << yytext << "\"" << endl;;)
+ templateLin = new read_policy_template_line (rsrc);
+ interpret_template_line (
+ templateLin, rsrc, set_data, random_asset,
+ assign_data_var_specified, expect, policy_info,
+ print_data, hash_data, asset_name, assign_data_var, parsed_asset,
+ nesting_level == 0 /* create call unless inside {} */,
+ dont_create_asset /* if no such asset exists, fail the call */,
+ yes_fill_in_template, 0
+ );
+ }
+ ;
+
+remove_command:
+ REMOVE SST sst_remove_args {
+ IVM(cout << "Remove SST command: \"" << yytext << "\"" << endl;;)
+ templateLin = new remove_sst_template_line (rsrc);
+ interpret_template_line (
+ templateLin, rsrc, set_data, random_asset,
+ assign_data_var_specified, expect, policy_info,
+ print_data, hash_data, asset_name, assign_data_var, parsed_asset,
+ nesting_level == 0 /* create call unless inside {} */,
+ dont_create_asset /* don't create an asset being deleted */,
+ yes_fill_in_template, 0
+ );
+ }
+ | REMOVE KEY key_remove_args {
+ IVM(cout << "Remove key command: \"" << yytext << "\"" << endl;;)
+ templateLin = new remove_key_template_line (rsrc);
+ templateLin->asset_info.set_name (asset_name); // set in key_asset_name, below
+ interpret_template_line (
+ templateLin, rsrc, set_data, random_asset,
+ assign_data_var_specified, expect, policy_info,
+ print_data, hash_data, asset_name, assign_data_var, parsed_asset,
+ nesting_level == 0 /* create call unless inside {} */,
+ dont_create_asset /* don't create an asset being deleted */,
+ yes_fill_in_template, 0
+ );
+ }
+ ;
+
+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. */
+ IVM(cout << "Secure hash command: \"" << yytext << "\"" << endl;)
+ templateLin = new security_hash_template_line (rsrc);
+ templateLin->asset_info.set_name (asset_name);
+ templateLin->assign_data_var_specified = assign_data_var_specified;
+ templateLin->assign_data_var.assign (assign_data_var);
+ templateLin->expect = expect;
+ 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 : parsed_asset.asset_name_vector) {
+ /* Also copy into template line object's local vector: */
+ templateLin->asset_info.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 );
+ parsed_asset.asset_name_vector.clear();
+
+
+ }
+ ;
+
+done_command: DONE {
+ if (nesting_level != 0) {
+ cerr << "\n\"done\" only available at outer-most { } nesting level."
+ << endl;
+ exit (702);
+ } else {
+ YYACCEPT;
+ }
+ }
+ ;
+
+literal_or_random_data:
+ DATA LITERAL {
+ IVM(cout << "Create from literal data: \"" << flush;)
+ set_data.random_data = false;
+ set_data.string_specified = true;
+ 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;)
+ }
+ | DATA STAR { /* TF-Fuzz supplies random data */
+ IVM(cout << "Create from random data" << endl;)
+ set_data.randomize();
+ literal.assign (set_data.get()); /* just in case something uses literal */
+ set_data.random_data = true;
+ set_data.string_specified = false;
+ }
+ ;
+
+ /* Root-command parameters: */
+sst_set_base_args:
+ sst_asset_name literal_or_random_data
+ | sst_asset_name {
+ IVM(cout << "SST-create from random data (no 'data *')" << endl;)
+ set_data.randomize();
+ literal.assign (set_data.get()); /* just in case something uses literal */
+ }
+ | sst_asset_name VAR IDENTIFIER { /* set from variable */
+ IVM(cout << "SST-set set from variable: \"" << flush;)
+ 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 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 if so, write code to write code to
+ set data appropriately from the file. */
+ }
+ ;
+
+sst_set_extended_args:
+ %empty /* nothing */
+ | FLAG sst_flags {
+ IVM(cout << "SST creation flags" << endl;)
+ IVM(cout << yytext << "\"" << endl;)
+ }
+ ;
+
+sst_flags:
+ %empty /* nothing */
+ | sst_flag sst_flags {
+ IVM(cout << "SST creation flag" << endl;)
+ IVM(cout << yytext << "\"" << endl;)
+ }
+ ;
+
+sst_flag: none | write_once | no_rp | no_conf;
+
+none : NONE {
+ set_data.flags_string = "PSA_STORAGE_FLAG_NONE";
+ /* TODO: grab from boilerplate */
+ IVM(cout << "SST no storage flag: " << yytext << "\"" << endl;)
+ }
+ ;
+
+write_once : WRITE_ONCE {
+ set_data.flags_string = "PSA_STORAGE_FLAG_WRITE_ONCE";
+ /* TODO: grab from boilerplate */
+ IVM(cout << "SST write-once flag: " << yytext << "\"" << endl;)
+ }
+ ;
+
+no_rp : NO_RP {
+ set_data.flags_string = "PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION";
+ /* TODO: grab from boilerplate */
+ IVM(cout << "SST no-replay-protection flag: "
+ << yytext << "\"" << endl;)
+ }
+ ;
+
+no_conf : NO_CONF {
+ set_data.flags_string = "PSA_STORAGE_FLAG_NO_CONFIDENTIALITY";
+ /* TODO: grab from boilerplate */
+ IVM(cout << "SST no-confidentiality flag: " << yytext
+ << "\"" << endl;)
+ }
+ ;
+
+sst_offset_spec:
+ NUMBER_TOK {
+ IVM(cout << "SST-data offset: \"" << flush;)
+ set_data.data_offset = atol(yytext);
+ IVM(cout << yytext << "\"" << endl;)
+ }
+ ;
+
+
+sst_read_args:
+ sst_asset_name read_args sst_read_extended_args {
+ IVM(cout << "SST-read arguments: " << yytext << "\"" << endl;)
+ }
+ ;
+
+read_args:
+ VAR IDENTIFIER { /* dump to variable */
+ IVM(cout << "Read dump to variable: \"" << flush;)
+ assign_data_var.assign (identifier);
+ assign_data_var_specified = true;
+ expect.data_specified = false;
+ expect.data_var_specified = false;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+ | CHECK read_args_var_name { /* check against variable */
+ IVM(cout << "Read check against variable: \""
+ << yytext << "\"" << endl;)
+ set_data.set (literal);
+ assign_data_var_specified = false;
+ expect.data_specified = false;
+ expect.data_var_specified = true;
+ expect.data_var = identifier;
+ }
+ | CHECK LITERAL { /* check against literal */
+ IVM(cout << "Read check against literal: " << flush;)
+ 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; /* don't read variable */
+ expect.data_specified = true; /* check against literal data */
+ expect.data_var_specified = false; /* don't check against variable */
+ IVM(cout << yytext << endl;)
+ }
+ | PRINT { /* print out content in test log */
+ IVM(cout << "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;)
+ }
+ | HASH { /* hash the data and save for later comparison */
+ IVM(cout << "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;)
+ }
+ | DFNAME sst_asset_dump_file_path { /* dump to file */
+ IVM(cout << "Read dump to file: \""
+ << yytext << "\"" << endl;)
+ set_data.literal_data_not_file = set_data.random_data = false;
+ }
+ ;
+
+sst_read_extended_args:
+ %empty /* nothing */
+ | OFFSET sst_offset_spec {
+ IVM(cout << "SST data offset" << endl;)
+ set_data.data_offset = atol(yytext);
+ IVM(cout << yytext << "\"" << endl;)
+ }
+ ;
+
+sst_remove_args:
+ sst_asset_name | random_picked_asset {
+ IVM(cout << "SST-remove arguments: \""
+ << yytext << "\"" << endl;)
+ }
+ ;
+
+asset_designator:
+ NAME ASSET_IDENTIFIER_LIST {
+ IVM(cout << "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 randomly choose existing asset */
+ parsed_asset.id_n_not_name = false;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+ | NAME STAR {
+ IVM(cout << "Asset random identifier: \"" << flush;)
+ random_name = true;
+ rand_data_length = 4 + (rand() % 5);
+ gib.word (false, gib_buff, gib_buff + rand_data_length - 1);
+ aid.assign (gib_buff);
+ parsed_asset.asset_name_vector.push_back (aid);
+ random_asset = psa_asset_usage::all; /* don't randomly choose existing asset */
+ parsed_asset.id_n_not_name = false;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+ ;
+single_existing_asset:
+ IDENTIFIER {
+ IVM(cout << "Single existing asset by name: \"" << flush;)
+ random_name = false;
+ policy_info.asset_3_name.assign (identifier);
+ random_asset = psa_asset_usage::all; /* don't randomly choose existing asset */
+ parsed_asset.id_n_not_name = false;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+ | random_picked_asset
+ ;
+
+random_picked_asset:
+ STAR ACTIVE {
+ IVM(cout << "Asset random active: \"" << flush;)
+ random_asset = psa_asset_usage::active;
+ parsed_asset.id_n_not_name = false;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+ | STAR DELETED {
+ IVM(cout << "Asset random deleted: \"" << flush;)
+ random_asset = psa_asset_usage::deleted;
+ parsed_asset.id_n_not_name = false;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+ ;
+
+sst_asset_name:
+ asset_designator
+ | UID ASSET_NUMBER_LIST {
+ IVM(cout << "SST-asset UID list: \"" << flush;)
+ random_name = false;
+ random_asset = psa_asset_usage::all; /* don't randomly choose existing asset */
+ parsed_asset.id_n_not_name = true;
+ parsed_asset.id_n_specified = true;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+ | UID STAR {
+ IVM(cout << "SST-asset random UID: \"" << flush;)
+ parsed_asset.id_n_not_name = true;
+ random_name = false;
+ nid = 100 + (rand() % 10000);
+ parsed_asset.asset_id_n_vector.push_back (nid);
+ random_asset = psa_asset_usage::all; /* don't randomly choose existing asset */
+ IVM(cout << yytext << "\"" << endl;)
+ }
+ ;
+
+sst_asset_set_file_path:
+ FILE_PATH {
+ IVM(cout << "SST-asset-create file path: \"" << flush;)
+ IVM(cout << yytext << "\"" << endl;)
+ }
+ ;
+
+read_args_var_name:
+ IDENTIFIER {
+ IVM(cout << "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_size:
+ NUMBER_TOK {
+ IVM(cout << "Key size: \"" << flush;)
+ policy_info.n_bits = atol(yytext);
+ IVM(cout << yytext << "\"" << endl;)
+ }
+ ;
+
+policy_usage_list: ATTR policy_usage policy_usages; /* at least one usage */
+
+policy_usages:
+ %empty /* nothing */
+ | policy_usage policy_usages {
+ IVM(cout << "Key-policy usages at line number " << dec << yylineno
+ << "." << endl;)
+ }
+ ;
+
+export : EXPORT {
+ policy_info.exportable = true;
+ IVM(cout << "Exportable key true: " << yytext << "\"" << endl;)
+ }
+ ;
+
+noexport : NOEXPORT {
+ policy_info.exportable = false;
+ IVM(cout << "Non-exportable key: " << yytext << "\"" << endl;)
+ }
+ ;
+
+copy : COPY {
+ policy_info.copyable = true;
+ IVM(cout << "Copyable key true: " << yytext << "\"" << endl;)
+ }
+ ;
+
+nocopy : NOCOPY {
+ policy_info.copyable = false;
+ IVM(cout << "Non-copyable key: " << yytext << "\"" << endl;)
+ }
+ ;
+
+encrypt : ENCRYPT {
+ policy_info.can_encrypt = true;
+ IVM(cout << "Encryption key true: " << yytext << "\"" << endl;)
+ }
+ ;
+
+noencrypt : NOENCRYPT {
+ policy_info.can_encrypt = false;
+ IVM(cout << "Non-encryption key: " << yytext << "\"" << endl;)
+ }
+ ;
+
+decrypt : DECRYPT {
+ policy_info.can_decrypt = true;
+ IVM(cout << "Decryption key true: " << yytext << "\"" << endl;)
+ }
+ ;
+
+nodecrypt : NODECRYPT {
+ policy_info.can_decrypt = false;
+ IVM(cout << "Non-decryption key: " << yytext << "\"" << endl;)
+ }
+ ;
+
+sign : SIGN {
+ policy_info.can_sign = true;
+ IVM(cout << "Signing key true: " << yytext << "\"" << endl;)
+ }
+ ;
+
+nosign : NOSIGN {
+ policy_info.can_sign = false;
+ IVM(cout << "Non-signing key: " << yytext << "\"" << endl;)
+ }
+ ;
+
+verify : VERIFY {
+ policy_info.can_verify = true;
+ IVM(cout << "Verify key true: " << yytext << "\"" << endl;)
+ }
+ ;
+
+noverify : NOVERIFY {
+ policy_info.can_verify = false;
+ IVM(cout << "Non-verify key: " << yytext << "\"" << endl;)
+ }
+ ;
+
+derive : DERIVE {
+ policy_info.derivable = true;
+ IVM(cout << "Derivable key true: " << yytext << "\"" << endl;)
+ }
+ ;
+
+noderive : NODERIVE {
+ policy_info.derivable = false;
+ IVM(cout << "Non-derivable key: " << yytext << "\"" << endl;)
+ }
+ ;
+
+persistent : PERSISTENT {
+ policy_info.persistent = true;
+ IVM(cout << "Persistent key: " << yytext << "\"" << endl;)
+ }
+ ;
+
+volatle : VOLATILE {
+ policy_info.persistent = false;
+ IVM(cout << "Volatile key: " << yytext << "\"" << endl;)
+ }
+ ;
+
+policy_usage:
+ export | copy | encrypt | decrypt | sign | verify | derive
+ | noexport | nocopy | noencrypt | nodecrypt | nosign | noverify
+ | noderive | persistent | volatle | key_size {
+ IVM(cout << "Policy usage: " << yytext << "\"" << endl;)
+ }
+ ;
+
+policy_type:
+ TYPE IDENTIFIER {
+ // Change type identifier, e.g., from "raw_data" to PSA_KEY_TYPE_RAW_DATA:
+ identifier = formalize (identifier, "PSA_KEY_TYPE_");
+ policy_info.key_type = identifier;
+ IVM(cout << "Policy type: \""
+ << policy_info.key_type << "\"" << endl;)
+ }
+
+policy_algorithm:
+ ALG IDENTIFIER {
+ // Change type identifier, e.g., from "sha_256" to PSA_ALG_SHA_256:
+ identifier = formalize (identifier, "PSA_ALG_");
+ policy_info.key_algorithm = identifier;
+ IVM(cout << "Policy algorithm: \""
+ << policy_info.key_algorithm << "\"" << endl;)
+ }
+
+policy_specs:
+ %empty /* nothing */
+ | policy_spec policy_specs {
+ IVM(cout << "Key-policy specs at line number " << dec << yylineno
+ << "." << endl;)
+ }
+ ;
+
+policy_spec: policy_usage_list | policy_type | policy_algorithm;
+
+policy_asset_spec:
+ %empty /* nothing */
+ | NAME ASSET_IDENTIFIER_LIST {
+ IVM(cout << "policy-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 randomly choose existing asset */
+ parsed_asset.id_n_not_name = false;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+ | NAME STAR {
+ IVM(cout << "policy-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);
+ parsed_asset.asset_name_vector.push_back (aid);
+ random_asset = psa_asset_usage::all; /* don't randomly choose existing asset */
+ parsed_asset.id_n_not_name = false;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+ ;
+
+policy_asset_name:
+ NAME IDENTIFIER {
+ IVM(cout << "policy-asset identifier list: \"" << flush;)
+ random_name = false;
+ policy_info.get_policy_from_key = false;
+ asset_name.assign (identifier); /* TODO: Not sure this ultimately has any effect... */
+ parsed_asset.asset_name_vector.push_back (identifier);
+ random_asset = psa_asset_usage::all; /* don't randomly choose existing asset */
+ parsed_asset.id_n_not_name = false;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+ | STAR ACTIVE {
+ IVM(cout << "policy-asset random active: \"" << flush;)
+ policy_info.get_policy_from_key = false;
+ random_asset = psa_asset_usage::active;
+ parsed_asset.id_n_not_name = false;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+ | STAR DELETED {
+ IVM(cout << "policy-asset random deleted: \"" << flush;)
+ policy_info.get_policy_from_key = false;
+ random_asset = psa_asset_usage::deleted;
+ parsed_asset.id_n_not_name = false;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+ | KEY IDENTIFIER {
+ IVM(cout << "policy-asset specified by key: \"" << flush;)
+ policy_info.get_policy_from_key = true;
+ random_name = false;
+ asset_name.assign (identifier); /* ask this key what it's policy is */
+ random_asset = psa_asset_usage::all; /* don't randomly choose existing asset */
+ parsed_asset.id_n_not_name = false;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+ ;
+
+policy_set_args:
+ policy_asset_spec policy_specs {
+ IVM(cout << "Policy-create arguments: \"" << yytext << "\"" << endl;)
+ }
+ ;
+
+policy_read_args:
+ policy_asset_name read_args {
+ IVM(cout << "Policy-read arguments: " << yytext << "\"" << endl;)
+ }
+ ;
+
+key_set_sources:
+ %empty /* nothing */
+ | key_set_source key_set_sources {
+ IVM(cout << "Key-set sources at Line number "
+ << yytext << "\"" << endl;)
+ }
+ ;
+
+key_set_source:
+ literal_or_random_data {
+ IVM(cout << "Key-set sources, literal or random data: "
+ << yytext << "\"" << endl;)
+ }
+ | POLICY IDENTIFIER {
+ IVM(cout << "Key-set sources, explicitly-specified policy name: "
+ << flush;)
+ policy_info.asset_2_name = identifier; /* policy */
+ /* Make note that key data (key material) was not specified: */
+ IVM(cout << yytext << "\"" << endl;)
+ }
+ ;
+
+key_data_or_not:
+ %empty /* nothing */
+ | literal_or_random_data {
+ IVM(cout << "Key data, literal or random data: "
+ << yytext << "\"" << endl;)
+ }
+ ;
+
+key_set_args:
+ asset_designator key_set_sources {
+ IVM(cout << "Key-create from data, policy, or nothing (default): \""
+ << yytext << "\"" << endl;)
+ policy_info.copy_key = false;
+ policy_info.implicit_policy = false;
+ }
+ | asset_designator FROM single_existing_asset POLICY IDENTIFIER {
+ IVM(cout << "Key-copy from other key: \"" << flush;)
+ policy_info.asset_2_name = identifier; /* policy */
+ policy_info.copy_key = true;
+ policy_info.implicit_policy = false;
+ IVM(cout << yytext << "\"" << endl;)
+ }
+ | asset_designator key_data_or_not WITH policy_specs {
+ IVM(cout << "Key-create directly specifying policy attributes (implicit policy): \""
+ << yytext << "\"" << endl;)
+ policy_info.copy_key = false;
+ policy_info.implicit_policy = true;
+ cerr << "\nError: Defining keys with implicit policies is not yet implemented."
+ << endl;
+ exit (772);
+ }
+ ;
+
+key_remove_args:
+ asset_designator {
+ IVM(cout << "Key-remove arguments: \""
+ << yytext << "\"" << endl;)
+ }
+ ;
+
+key_read_args:
+ asset_designator read_args {
+ IVM(cout << "Key dump: \"" << 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:
+ %empty /* nothing */
+ | ASSET_NUMBER ASSET_NUMBERS;
+
+ASSET_NUMBER:
+ NUMBER_TOK {
+ IVM(cout << "ASSET_NUMBER: \"" << flush;)
+ nid = atol(yytext);
+ parsed_asset.asset_id_n_vector.push_back (nid);
+ IVM(cout << yytext << "\"" << endl;)
+ }
+ ;
+
+ /* ASSET_IDENTIFIER are used specifically for lists of assets within a singletemplate
+ line. That, as opposed to list of identifers in general. The difference is the
+ need to queue ASSET_IDENTIFIERS up into parsed_asset.asset_name_vector, and have to
+ do so here before they "vanish." */
+ASSET_IDENTIFIER_LIST:
+ ASSET_IDENTIFIER ASSET_IDENTIFIERS; /* (at least one) */
+
+ASSET_IDENTIFIERS:
+ %empty /* nothing */
+ | ASSET_IDENTIFIER ASSET_IDENTIFIERS;
+
+ASSET_IDENTIFIER:
+ IDENTIFIER_TOK {
+ IVM(cout << "ASSET_IDENTIFIER: \"" << flush;)
+ aid = identifier = yytext;
+ parsed_asset.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 string: " << flush;)
+ literal = yytext;
+ literal_is_string = true;
+ IVM(cout << yytext << endl;)
+ }
+ | HEX_LIST {
+ IVM(cout << "LITERAL hex-value list: " << flush;)
+ literal = yytext;
+ literal_is_string = false;
+ IVM(cout << yytext << endl;)
+ }
+ ;
+
+
+%%
+
diff --git a/tf_fuzz/regression/000001_set_sst_uid_data_expect_pass/check.py b/tf_fuzz/regression/000001_set_sst_uid_data_expect_pass/check.py
new file mode 100644
index 0000000..1bc5cbe
--- /dev/null
+++ b/tf_fuzz/regression/000001_set_sst_uid_data_expect_pass/check.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+'''
+ Please read .../tf_fuzz/regression/README to understand this code.
+
+ Please also read the comments in .../tf_fuzz/regression/regress_lib/line_by_line.py.
+'''
+
+import sys, os, re, string, pdb
+sys.path.append ("../regress_lib")
+import line_by_line
+
+
+# Describe script usage:
+def usage():
+ print ('''
+ Command-line parameters:
+ 1. The test-template file, nominally named "template",
+ 2. The expected combined stdout/stderr output, nominally named "exp_stdout_stderr",
+ 3. The actual/generated combined stdout/stderr output, nominally named "stdout_stderr",
+ 4. The expected .c test file, nominally named "exp_test.c", and
+ 5. The actual, generated .c test file, nominally named "test.c".
+
+ Optionally, *before* these five arguments, you may add switches thus:
+ "--v" for verbose mode, to view line-by-line comparisons actual vs. expected,
+ "--q" to only print error messages and a successful-completion message,
+ "--qq" same as --q but not even printing out the completion message, and
+ "--s 12345" to run TF-Fuzz with seed value 12345 (or whatever).
+ ''')
+
+
+def main():
+ # See if we're supposed to be quiet:
+ loud = quiet = ultra_quiet = False
+ seed = ""
+ while sys.argv[1][0] == "-":
+ if sys.argv[1] == "--v":
+ loud = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--q":
+ quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--qq":
+ quiet = ultra_quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--s":
+ sys.argv.pop(1)
+ seed = sys.argv[1]
+ sys.argv.pop(1)
+ if not seed.isnumeric():
+ print ('The --s seed argument was not a number.')
+ usage()
+ sys.exit(1)
+
+ # Run TF-Fuzz:
+ if not quiet: print ("Running TF-Fuzz... ")
+ os.system ('rm -f stdout_stderr test.c')
+ command = '../../tfz -v ./' + sys.argv[1] + ' ./' + sys.argv[5]
+ command += ' ' + seed + ' >' + sys.argv[3] + ' 2>&1'
+ if loud:
+ print (command)
+ if os.system (command) == 0:
+ if not quiet: print ("TF-Fuzz run complete.")
+ else:
+ print ('Could not run TF-Fuzz; please see stdout_stderr file.')
+ sys.exit(2)
+
+ # Attempt to open files indicated on command line:
+ if len(sys.argv) != 6:
+ message = '{} requires 5 command-line arguments. Exiting.'
+ print (message.format(sys.argv[0]), file=sys.stderr)
+ usage()
+ sys.exit(3)
+ template_file_name = sys.argv[1]
+ exp_stdout_file_name = sys.argv[2]
+ act_stdout_file_name = sys.argv[3]
+ exp_test_file_name = sys.argv[4]
+ act_test_file_name = sys.argv[5]
+
+ try:
+ template_file = open (template_file_name, 'rt')
+ exp_stdout_file = open (exp_stdout_file_name, 'rt')
+ act_stdout_file = open (act_stdout_file_name, 'rt')
+ exp_test_file = open (exp_test_file_name, 'rt')
+ act_test_file = open (act_test_file_name, 'rt')
+ except FileNotFoundError:
+ print ('One or more files could not be found.')
+ usage();
+ sys.exit(4)
+ except:
+ print ('Something went wrong trying to open the input files.')
+ usage();
+ sys.exit(5)
+ else:
+ message = '\nInput files:\n {},\n {},\n {},\n'
+ message += ' {}, and\n {}\nopened successfully.\n'
+ if not quiet:
+ print (message.format (template_file_name, exp_stdout_file_name,
+ act_stdout_file_name, exp_test_file_name, act_test_file_name))
+
+ # Check it all:
+ if not quiet: print ("\nChecking test C file: ", end="")
+ line_by_line.check_file ( exp_test_file, exp_test_file_name,
+ act_test_file, act_test_file_name,
+ loud, quiet, ultra_quiet )
+ if not quiet: print ("Checking stdout and stderr: ", end="")
+ line_by_line.check_file ( exp_stdout_file, exp_stdout_file_name,
+ act_stdout_file, act_stdout_file_name,
+ loud, quiet, ultra_quiet )
+
+ # Ran to completion normally, so pass:
+ if not ultra_quiet: print ("Regression test passed.")
+ sys.exit(0)
+
+if __name__ == "__main__": main()
diff --git a/tf_fuzz/regression/000001_set_sst_uid_data_expect_pass/exp_stdout_stderr b/tf_fuzz/regression/000001_set_sst_uid_data_expect_pass/exp_stdout_stderr
new file mode 100644
index 0000000..1976f7b
--- /dev/null
+++ b/tf_fuzz/regression/000001_set_sst_uid_data_expect_pass/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 create an SST asset
+ASSET_NUMBER: "104"
+SST-asset UID list: "data"
+LITERAL string: "Very simple test"
+Create from literal data: ""Very simple test""
+Set SST command: "expect"
+Appended to end of call sequence: SST-set call.
+Set command: "expect"
+Expect pass clause: "pass"
+Command with expect: ";"
+Lines: Line number 3.
+Lines: Line number 3.
+Call sequence generated.
+Simulating call sequence...
+Call sequence:
+ SST-set call for asset SST_ID_104
+Writing test file, ./test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tf_fuzz/regression/000001_set_sst_uid_data_expect_pass/exp_test.c b/tf_fuzz/regression/000001_set_sst_uid_data_expect_pass/exp_test.c
new file mode 100644
index 0000000..04b84e9
--- /dev/null
+++ b/tf_fuzz/regression/000001_set_sst_uid_data_expect_pass/exp_test.c
@@ -0,0 +1,61 @@
+/*
+ * 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 "tfm_memory_utils.h"
+#include "psa/crypto.h"
+#include "psa/crypto_sizes.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;
+ /* Variables (etc.) to initialize and check PSA assets: */
+ static uint8_t SST_ID_104_set_data[] = "Very simple test";
+ static uint32_t SST_ID_104_set_length = 16;
+ (void)sst_status;
+ /* "void" to prevent unused-variable warning, since the variable may not
+ * be used in this particular test case.
+ */
+
+ 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");
+
+
+ /* PSA calls to test: */
+ /\* Creating SST asset UID = 104 with data "Very simpl...". \*/
+ sst_status = psa_ps_set(104, SST_ID_104_set_length, SST_ID_104_set_data,
+ PSA_STORAGE_FLAG_[A-Z_]+\);
+ 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/tf_fuzz/regression/000001_set_sst_uid_data_expect_pass/template b/tf_fuzz/regression/000001_set_sst_uid_data_expect_pass/template
new file mode 100644
index 0000000..7b84f11
--- /dev/null
+++ b/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/tf_fuzz/regression/000002_set_sst_name_data_expect_nothing/check.py b/tf_fuzz/regression/000002_set_sst_name_data_expect_nothing/check.py
new file mode 100644
index 0000000..1bc5cbe
--- /dev/null
+++ b/tf_fuzz/regression/000002_set_sst_name_data_expect_nothing/check.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+'''
+ Please read .../tf_fuzz/regression/README to understand this code.
+
+ Please also read the comments in .../tf_fuzz/regression/regress_lib/line_by_line.py.
+'''
+
+import sys, os, re, string, pdb
+sys.path.append ("../regress_lib")
+import line_by_line
+
+
+# Describe script usage:
+def usage():
+ print ('''
+ Command-line parameters:
+ 1. The test-template file, nominally named "template",
+ 2. The expected combined stdout/stderr output, nominally named "exp_stdout_stderr",
+ 3. The actual/generated combined stdout/stderr output, nominally named "stdout_stderr",
+ 4. The expected .c test file, nominally named "exp_test.c", and
+ 5. The actual, generated .c test file, nominally named "test.c".
+
+ Optionally, *before* these five arguments, you may add switches thus:
+ "--v" for verbose mode, to view line-by-line comparisons actual vs. expected,
+ "--q" to only print error messages and a successful-completion message,
+ "--qq" same as --q but not even printing out the completion message, and
+ "--s 12345" to run TF-Fuzz with seed value 12345 (or whatever).
+ ''')
+
+
+def main():
+ # See if we're supposed to be quiet:
+ loud = quiet = ultra_quiet = False
+ seed = ""
+ while sys.argv[1][0] == "-":
+ if sys.argv[1] == "--v":
+ loud = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--q":
+ quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--qq":
+ quiet = ultra_quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--s":
+ sys.argv.pop(1)
+ seed = sys.argv[1]
+ sys.argv.pop(1)
+ if not seed.isnumeric():
+ print ('The --s seed argument was not a number.')
+ usage()
+ sys.exit(1)
+
+ # Run TF-Fuzz:
+ if not quiet: print ("Running TF-Fuzz... ")
+ os.system ('rm -f stdout_stderr test.c')
+ command = '../../tfz -v ./' + sys.argv[1] + ' ./' + sys.argv[5]
+ command += ' ' + seed + ' >' + sys.argv[3] + ' 2>&1'
+ if loud:
+ print (command)
+ if os.system (command) == 0:
+ if not quiet: print ("TF-Fuzz run complete.")
+ else:
+ print ('Could not run TF-Fuzz; please see stdout_stderr file.')
+ sys.exit(2)
+
+ # Attempt to open files indicated on command line:
+ if len(sys.argv) != 6:
+ message = '{} requires 5 command-line arguments. Exiting.'
+ print (message.format(sys.argv[0]), file=sys.stderr)
+ usage()
+ sys.exit(3)
+ template_file_name = sys.argv[1]
+ exp_stdout_file_name = sys.argv[2]
+ act_stdout_file_name = sys.argv[3]
+ exp_test_file_name = sys.argv[4]
+ act_test_file_name = sys.argv[5]
+
+ try:
+ template_file = open (template_file_name, 'rt')
+ exp_stdout_file = open (exp_stdout_file_name, 'rt')
+ act_stdout_file = open (act_stdout_file_name, 'rt')
+ exp_test_file = open (exp_test_file_name, 'rt')
+ act_test_file = open (act_test_file_name, 'rt')
+ except FileNotFoundError:
+ print ('One or more files could not be found.')
+ usage();
+ sys.exit(4)
+ except:
+ print ('Something went wrong trying to open the input files.')
+ usage();
+ sys.exit(5)
+ else:
+ message = '\nInput files:\n {},\n {},\n {},\n'
+ message += ' {}, and\n {}\nopened successfully.\n'
+ if not quiet:
+ print (message.format (template_file_name, exp_stdout_file_name,
+ act_stdout_file_name, exp_test_file_name, act_test_file_name))
+
+ # Check it all:
+ if not quiet: print ("\nChecking test C file: ", end="")
+ line_by_line.check_file ( exp_test_file, exp_test_file_name,
+ act_test_file, act_test_file_name,
+ loud, quiet, ultra_quiet )
+ if not quiet: print ("Checking stdout and stderr: ", end="")
+ line_by_line.check_file ( exp_stdout_file, exp_stdout_file_name,
+ act_stdout_file, act_stdout_file_name,
+ loud, quiet, ultra_quiet )
+
+ # Ran to completion normally, so pass:
+ if not ultra_quiet: print ("Regression test passed.")
+ sys.exit(0)
+
+if __name__ == "__main__": main()
diff --git a/tf_fuzz/regression/000002_set_sst_name_data_expect_nothing/exp_stdout_stderr b/tf_fuzz/regression/000002_set_sst_name_data_expect_nothing/exp_stdout_stderr
new file mode 100644
index 0000000..97c20e8
--- /dev/null
+++ b/tf_fuzz/regression/000002_set_sst_name_data_expect_nothing/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 give assets a human name
+ASSET_IDENTIFIER: "forecast"
+Asset identifier list: "data"
+LITERAL string: "sunny with a 30% chance of weather!"
+Create from literal data: ""sunny with a 30% chance of weather!""
+Set SST command: "expect"
+Appended to end of call sequence: SST-set call.
+Set command: "expect"
+Expect nothing clause: "nothing"
+Command with expect: ";"
+Lines: Line number 3.
+Lines: Line number 3.
+Call sequence generated.
+Simulating call sequence...
+Call sequence:
+ SST-set call for asset forecast
+Writing test file, ./test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tf_fuzz/regression/000002_set_sst_name_data_expect_nothing/exp_test.c b/tf_fuzz/regression/000002_set_sst_name_data_expect_nothing/exp_test.c
new file mode 100644
index 0000000..e792c9b
--- /dev/null
+++ b/tf_fuzz/regression/000002_set_sst_name_data_expect_nothing/exp_test.c
@@ -0,0 +1,58 @@
+/*
+ * 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 "tfm_memory_utils.h"
+#include "psa/crypto.h"
+#include "psa/crypto_sizes.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;
+ /* Variables (etc.) to initialize and check PSA assets: */
+ static uint8_t forecast_set_data[] = "sunny with a 30% chance of weather!";
+ static uint32_t forecast_set_length = 35;
+ (void)sst_status;
+ /* "void" to prevent unused-variable warning, since the variable may not
+ * be used in this particular test case.
+ */
+
+ 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");
+
+
+ /* PSA calls to test: */
+ /\* Creating SST asset "forecast," with data "sunny with...". \*/
+ sst_status = psa_ps_set\(@@@001@@@, forecast_set_length, forecast_set_data,
+ PSA_STORAGE_FLAG_[A-Z_]+\);
+ /* (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/tf_fuzz/regression/000002_set_sst_name_data_expect_nothing/template b/tf_fuzz/regression/000002_set_sst_name_data_expect_nothing/template
new file mode 100644
index 0000000..7292031
--- /dev/null
+++ b/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/tf_fuzz/regression/000003_set_sst_name_data/check.py b/tf_fuzz/regression/000003_set_sst_name_data/check.py
new file mode 100644
index 0000000..1bc5cbe
--- /dev/null
+++ b/tf_fuzz/regression/000003_set_sst_name_data/check.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+'''
+ Please read .../tf_fuzz/regression/README to understand this code.
+
+ Please also read the comments in .../tf_fuzz/regression/regress_lib/line_by_line.py.
+'''
+
+import sys, os, re, string, pdb
+sys.path.append ("../regress_lib")
+import line_by_line
+
+
+# Describe script usage:
+def usage():
+ print ('''
+ Command-line parameters:
+ 1. The test-template file, nominally named "template",
+ 2. The expected combined stdout/stderr output, nominally named "exp_stdout_stderr",
+ 3. The actual/generated combined stdout/stderr output, nominally named "stdout_stderr",
+ 4. The expected .c test file, nominally named "exp_test.c", and
+ 5. The actual, generated .c test file, nominally named "test.c".
+
+ Optionally, *before* these five arguments, you may add switches thus:
+ "--v" for verbose mode, to view line-by-line comparisons actual vs. expected,
+ "--q" to only print error messages and a successful-completion message,
+ "--qq" same as --q but not even printing out the completion message, and
+ "--s 12345" to run TF-Fuzz with seed value 12345 (or whatever).
+ ''')
+
+
+def main():
+ # See if we're supposed to be quiet:
+ loud = quiet = ultra_quiet = False
+ seed = ""
+ while sys.argv[1][0] == "-":
+ if sys.argv[1] == "--v":
+ loud = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--q":
+ quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--qq":
+ quiet = ultra_quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--s":
+ sys.argv.pop(1)
+ seed = sys.argv[1]
+ sys.argv.pop(1)
+ if not seed.isnumeric():
+ print ('The --s seed argument was not a number.')
+ usage()
+ sys.exit(1)
+
+ # Run TF-Fuzz:
+ if not quiet: print ("Running TF-Fuzz... ")
+ os.system ('rm -f stdout_stderr test.c')
+ command = '../../tfz -v ./' + sys.argv[1] + ' ./' + sys.argv[5]
+ command += ' ' + seed + ' >' + sys.argv[3] + ' 2>&1'
+ if loud:
+ print (command)
+ if os.system (command) == 0:
+ if not quiet: print ("TF-Fuzz run complete.")
+ else:
+ print ('Could not run TF-Fuzz; please see stdout_stderr file.')
+ sys.exit(2)
+
+ # Attempt to open files indicated on command line:
+ if len(sys.argv) != 6:
+ message = '{} requires 5 command-line arguments. Exiting.'
+ print (message.format(sys.argv[0]), file=sys.stderr)
+ usage()
+ sys.exit(3)
+ template_file_name = sys.argv[1]
+ exp_stdout_file_name = sys.argv[2]
+ act_stdout_file_name = sys.argv[3]
+ exp_test_file_name = sys.argv[4]
+ act_test_file_name = sys.argv[5]
+
+ try:
+ template_file = open (template_file_name, 'rt')
+ exp_stdout_file = open (exp_stdout_file_name, 'rt')
+ act_stdout_file = open (act_stdout_file_name, 'rt')
+ exp_test_file = open (exp_test_file_name, 'rt')
+ act_test_file = open (act_test_file_name, 'rt')
+ except FileNotFoundError:
+ print ('One or more files could not be found.')
+ usage();
+ sys.exit(4)
+ except:
+ print ('Something went wrong trying to open the input files.')
+ usage();
+ sys.exit(5)
+ else:
+ message = '\nInput files:\n {},\n {},\n {},\n'
+ message += ' {}, and\n {}\nopened successfully.\n'
+ if not quiet:
+ print (message.format (template_file_name, exp_stdout_file_name,
+ act_stdout_file_name, exp_test_file_name, act_test_file_name))
+
+ # Check it all:
+ if not quiet: print ("\nChecking test C file: ", end="")
+ line_by_line.check_file ( exp_test_file, exp_test_file_name,
+ act_test_file, act_test_file_name,
+ loud, quiet, ultra_quiet )
+ if not quiet: print ("Checking stdout and stderr: ", end="")
+ line_by_line.check_file ( exp_stdout_file, exp_stdout_file_name,
+ act_stdout_file, act_stdout_file_name,
+ loud, quiet, ultra_quiet )
+
+ # Ran to completion normally, so pass:
+ if not ultra_quiet: print ("Regression test passed.")
+ sys.exit(0)
+
+if __name__ == "__main__": main()
diff --git a/tf_fuzz/regression/000003_set_sst_name_data/exp_stdout_stderr b/tf_fuzz/regression/000003_set_sst_name_data/exp_stdout_stderr
new file mode 100644
index 0000000..19a9bdb
--- /dev/null
+++ b/tf_fuzz/regression/000003_set_sst_name_data/exp_stdout_stderr
@@ -0,0 +1,23 @@
+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"
+Asset identifier list: "data"
+LITERAL string: "I am the man"
+Create from literal data: ""I am the man""
+Set SST command: ";"
+Appended to end of call sequence: SST-set call.
+Set command: ";"
+Command with no expect: ";"
+Lines: Line number 3.
+Lines: Line number 3.
+Call sequence generated.
+Simulating call sequence...
+Call sequence:
+ SST-set call for asset jonathan
+Writing test file, ./test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tf_fuzz/regression/000003_set_sst_name_data/exp_test.c b/tf_fuzz/regression/000003_set_sst_name_data/exp_test.c
new file mode 100644
index 0000000..9dc4d24
--- /dev/null
+++ b/tf_fuzz/regression/000003_set_sst_name_data/exp_test.c
@@ -0,0 +1,61 @@
+/*
+ * 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 "tfm_memory_utils.h"
+#include "psa/crypto.h"
+#include "psa/crypto_sizes.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;
+ /* Variables (etc.) to initialize and check PSA assets: */
+ static uint8_t jonathan_set_data[] = "I am the man";
+ static uint32_t jonathan_set_length = 12;
+ (void)sst_status;
+ /* "void" to prevent unused-variable warning, since the variable may not
+ * be used in this particular test case.
+ */
+
+ 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\"");
+
+
+ /* PSA calls to test: */
+ /\* Creating SST asset "jonathan," with data "I am the m...". \*/
+ sst_status = psa_ps_set\(@@@001@@@, jonathan_set_length, jonathan_set_data,
+ PSA_STORAGE_FLAG_[A-Z_]+\);
+ 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/tf_fuzz/regression/000003_set_sst_name_data/template b/tf_fuzz/regression/000003_set_sst_name_data/template
new file mode 100644
index 0000000..820e3ab
--- /dev/null
+++ b/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/tf_fuzz/regression/000004_set_sst_name_rand_data/check.py b/tf_fuzz/regression/000004_set_sst_name_rand_data/check.py
new file mode 100644
index 0000000..1bc5cbe
--- /dev/null
+++ b/tf_fuzz/regression/000004_set_sst_name_rand_data/check.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+'''
+ Please read .../tf_fuzz/regression/README to understand this code.
+
+ Please also read the comments in .../tf_fuzz/regression/regress_lib/line_by_line.py.
+'''
+
+import sys, os, re, string, pdb
+sys.path.append ("../regress_lib")
+import line_by_line
+
+
+# Describe script usage:
+def usage():
+ print ('''
+ Command-line parameters:
+ 1. The test-template file, nominally named "template",
+ 2. The expected combined stdout/stderr output, nominally named "exp_stdout_stderr",
+ 3. The actual/generated combined stdout/stderr output, nominally named "stdout_stderr",
+ 4. The expected .c test file, nominally named "exp_test.c", and
+ 5. The actual, generated .c test file, nominally named "test.c".
+
+ Optionally, *before* these five arguments, you may add switches thus:
+ "--v" for verbose mode, to view line-by-line comparisons actual vs. expected,
+ "--q" to only print error messages and a successful-completion message,
+ "--qq" same as --q but not even printing out the completion message, and
+ "--s 12345" to run TF-Fuzz with seed value 12345 (or whatever).
+ ''')
+
+
+def main():
+ # See if we're supposed to be quiet:
+ loud = quiet = ultra_quiet = False
+ seed = ""
+ while sys.argv[1][0] == "-":
+ if sys.argv[1] == "--v":
+ loud = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--q":
+ quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--qq":
+ quiet = ultra_quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--s":
+ sys.argv.pop(1)
+ seed = sys.argv[1]
+ sys.argv.pop(1)
+ if not seed.isnumeric():
+ print ('The --s seed argument was not a number.')
+ usage()
+ sys.exit(1)
+
+ # Run TF-Fuzz:
+ if not quiet: print ("Running TF-Fuzz... ")
+ os.system ('rm -f stdout_stderr test.c')
+ command = '../../tfz -v ./' + sys.argv[1] + ' ./' + sys.argv[5]
+ command += ' ' + seed + ' >' + sys.argv[3] + ' 2>&1'
+ if loud:
+ print (command)
+ if os.system (command) == 0:
+ if not quiet: print ("TF-Fuzz run complete.")
+ else:
+ print ('Could not run TF-Fuzz; please see stdout_stderr file.')
+ sys.exit(2)
+
+ # Attempt to open files indicated on command line:
+ if len(sys.argv) != 6:
+ message = '{} requires 5 command-line arguments. Exiting.'
+ print (message.format(sys.argv[0]), file=sys.stderr)
+ usage()
+ sys.exit(3)
+ template_file_name = sys.argv[1]
+ exp_stdout_file_name = sys.argv[2]
+ act_stdout_file_name = sys.argv[3]
+ exp_test_file_name = sys.argv[4]
+ act_test_file_name = sys.argv[5]
+
+ try:
+ template_file = open (template_file_name, 'rt')
+ exp_stdout_file = open (exp_stdout_file_name, 'rt')
+ act_stdout_file = open (act_stdout_file_name, 'rt')
+ exp_test_file = open (exp_test_file_name, 'rt')
+ act_test_file = open (act_test_file_name, 'rt')
+ except FileNotFoundError:
+ print ('One or more files could not be found.')
+ usage();
+ sys.exit(4)
+ except:
+ print ('Something went wrong trying to open the input files.')
+ usage();
+ sys.exit(5)
+ else:
+ message = '\nInput files:\n {},\n {},\n {},\n'
+ message += ' {}, and\n {}\nopened successfully.\n'
+ if not quiet:
+ print (message.format (template_file_name, exp_stdout_file_name,
+ act_stdout_file_name, exp_test_file_name, act_test_file_name))
+
+ # Check it all:
+ if not quiet: print ("\nChecking test C file: ", end="")
+ line_by_line.check_file ( exp_test_file, exp_test_file_name,
+ act_test_file, act_test_file_name,
+ loud, quiet, ultra_quiet )
+ if not quiet: print ("Checking stdout and stderr: ", end="")
+ line_by_line.check_file ( exp_stdout_file, exp_stdout_file_name,
+ act_stdout_file, act_stdout_file_name,
+ loud, quiet, ultra_quiet )
+
+ # Ran to completion normally, so pass:
+ if not ultra_quiet: print ("Regression test passed.")
+ sys.exit(0)
+
+if __name__ == "__main__": main()
diff --git a/tf_fuzz/regression/000004_set_sst_name_rand_data/exp_stdout_stderr b/tf_fuzz/regression/000004_set_sst_name_rand_data/exp_stdout_stderr
new file mode 100644
index 0000000..916f354
--- /dev/null
+++ b/tf_fuzz/regression/000004_set_sst_name_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: to show how to randomize data
+ASSET_IDENTIFIER: "gibberish"
+Asset identifier list: "data"
+Create from random data
+Set SST command: "*"
+Appended to end of call sequence: SST-set call.
+Set command: "*"
+Command with no expect: ";"
+Lines: Line number 3.
+Lines: Line number 3.
+Call sequence generated.
+Simulating call sequence...
+Call sequence:
+ SST-set call for asset gibberish
+Writing test file, ./test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tf_fuzz/regression/000004_set_sst_name_rand_data/exp_test.c b/tf_fuzz/regression/000004_set_sst_name_rand_data/exp_test.c
new file mode 100644
index 0000000..2f56e4e
--- /dev/null
+++ b/tf_fuzz/regression/000004_set_sst_name_rand_data/exp_test.c
@@ -0,0 +1,61 @@
+/*
+ * 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 "tfm_memory_utils.h"
+#include "psa/crypto.h"
+#include "psa/crypto_sizes.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;
+ /* Variables (etc.) to initialize and check PSA assets: */
+ static uint8_t gibberish_set_data\[\] = "@@002@10@@[a-z\ ]*[\.\?\!]";
+ static uint32_t gibberish_set_length = \d+;
+ (void)sst_status;
+ /* "void" to prevent unused-variable warning, since the variable may not
+ * be used in this particular test case.
+ */
+
+ 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");
+
+
+ /* PSA calls to test: */
+ /\* Creating SST asset "gibberish," with data "@@002@10@@...". \*/
+ sst_status = psa_ps_set\(@@@001@@@, gibberish_set_length, gibberish_set_data,
+ PSA_STORAGE_FLAG_[A-Z_]+\);
+ 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/tf_fuzz/regression/000004_set_sst_name_rand_data/template b/tf_fuzz/regression/000004_set_sst_name_rand_data/template
new file mode 100644
index 0000000..912c23a
--- /dev/null
+++ b/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/tf_fuzz/regression/000005_set_sst_rand_name_rand_data/check.py b/tf_fuzz/regression/000005_set_sst_rand_name_rand_data/check.py
new file mode 100644
index 0000000..1bc5cbe
--- /dev/null
+++ b/tf_fuzz/regression/000005_set_sst_rand_name_rand_data/check.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+'''
+ Please read .../tf_fuzz/regression/README to understand this code.
+
+ Please also read the comments in .../tf_fuzz/regression/regress_lib/line_by_line.py.
+'''
+
+import sys, os, re, string, pdb
+sys.path.append ("../regress_lib")
+import line_by_line
+
+
+# Describe script usage:
+def usage():
+ print ('''
+ Command-line parameters:
+ 1. The test-template file, nominally named "template",
+ 2. The expected combined stdout/stderr output, nominally named "exp_stdout_stderr",
+ 3. The actual/generated combined stdout/stderr output, nominally named "stdout_stderr",
+ 4. The expected .c test file, nominally named "exp_test.c", and
+ 5. The actual, generated .c test file, nominally named "test.c".
+
+ Optionally, *before* these five arguments, you may add switches thus:
+ "--v" for verbose mode, to view line-by-line comparisons actual vs. expected,
+ "--q" to only print error messages and a successful-completion message,
+ "--qq" same as --q but not even printing out the completion message, and
+ "--s 12345" to run TF-Fuzz with seed value 12345 (or whatever).
+ ''')
+
+
+def main():
+ # See if we're supposed to be quiet:
+ loud = quiet = ultra_quiet = False
+ seed = ""
+ while sys.argv[1][0] == "-":
+ if sys.argv[1] == "--v":
+ loud = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--q":
+ quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--qq":
+ quiet = ultra_quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--s":
+ sys.argv.pop(1)
+ seed = sys.argv[1]
+ sys.argv.pop(1)
+ if not seed.isnumeric():
+ print ('The --s seed argument was not a number.')
+ usage()
+ sys.exit(1)
+
+ # Run TF-Fuzz:
+ if not quiet: print ("Running TF-Fuzz... ")
+ os.system ('rm -f stdout_stderr test.c')
+ command = '../../tfz -v ./' + sys.argv[1] + ' ./' + sys.argv[5]
+ command += ' ' + seed + ' >' + sys.argv[3] + ' 2>&1'
+ if loud:
+ print (command)
+ if os.system (command) == 0:
+ if not quiet: print ("TF-Fuzz run complete.")
+ else:
+ print ('Could not run TF-Fuzz; please see stdout_stderr file.')
+ sys.exit(2)
+
+ # Attempt to open files indicated on command line:
+ if len(sys.argv) != 6:
+ message = '{} requires 5 command-line arguments. Exiting.'
+ print (message.format(sys.argv[0]), file=sys.stderr)
+ usage()
+ sys.exit(3)
+ template_file_name = sys.argv[1]
+ exp_stdout_file_name = sys.argv[2]
+ act_stdout_file_name = sys.argv[3]
+ exp_test_file_name = sys.argv[4]
+ act_test_file_name = sys.argv[5]
+
+ try:
+ template_file = open (template_file_name, 'rt')
+ exp_stdout_file = open (exp_stdout_file_name, 'rt')
+ act_stdout_file = open (act_stdout_file_name, 'rt')
+ exp_test_file = open (exp_test_file_name, 'rt')
+ act_test_file = open (act_test_file_name, 'rt')
+ except FileNotFoundError:
+ print ('One or more files could not be found.')
+ usage();
+ sys.exit(4)
+ except:
+ print ('Something went wrong trying to open the input files.')
+ usage();
+ sys.exit(5)
+ else:
+ message = '\nInput files:\n {},\n {},\n {},\n'
+ message += ' {}, and\n {}\nopened successfully.\n'
+ if not quiet:
+ print (message.format (template_file_name, exp_stdout_file_name,
+ act_stdout_file_name, exp_test_file_name, act_test_file_name))
+
+ # Check it all:
+ if not quiet: print ("\nChecking test C file: ", end="")
+ line_by_line.check_file ( exp_test_file, exp_test_file_name,
+ act_test_file, act_test_file_name,
+ loud, quiet, ultra_quiet )
+ if not quiet: print ("Checking stdout and stderr: ", end="")
+ line_by_line.check_file ( exp_stdout_file, exp_stdout_file_name,
+ act_stdout_file, act_stdout_file_name,
+ loud, quiet, ultra_quiet )
+
+ # Ran to completion normally, so pass:
+ if not ultra_quiet: print ("Regression test passed.")
+ sys.exit(0)
+
+if __name__ == "__main__": main()
diff --git a/tf_fuzz/regression/000005_set_sst_rand_name_rand_data/exp_stdout_stderr b/tf_fuzz/regression/000005_set_sst_rand_name_rand_data/exp_stdout_stderr
new file mode 100644
index 0000000..5ead6c6
--- /dev/null
+++ b/tf_fuzz/regression/000005_set_sst_rand_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 how to randomize name and data
+Asset random identifier: "*"
+Create from random data
+Set SST command: "*"
+Appended to end of call sequence: SST-set call.
+Set command: "*"
+Command with no expect: ";"
+Lines: Line number 3.
+Lines: Line number 3.
+Call sequence generated.
+Simulating call sequence...
+Call sequence:
+ SST-set call for asset [a-z]+
+Writing test file, ./test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tf_fuzz/regression/000005_set_sst_rand_name_rand_data/exp_test.c b/tf_fuzz/regression/000005_set_sst_rand_name_rand_data/exp_test.c
new file mode 100644
index 0000000..288cb19
--- /dev/null
+++ b/tf_fuzz/regression/000005_set_sst_rand_name_rand_data/exp_test.c
@@ -0,0 +1,61 @@
+/*
+ * 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 "tfm_memory_utils.h"
+#include "psa/crypto.h"
+#include "psa/crypto_sizes.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;
+ /* Variables (etc.) to initialize and check PSA assets: */
+ static uint8_t @@@003@@@_set_data\[\] = "@@002@10@@[a-z\ ]*[\.\?\!]";
+ static uint32_t @@@003@@@_set_length = \d+;
+ (void)sst_status;
+ /* "void" to prevent unused-variable warning, since the variable may not
+ * be used in this particular test case.
+ */
+
+ 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");
+
+
+ /* PSA calls to test: */
+ /\* Creating SST asset "@@@003@@@," with data "@@002@10@@...". \*/
+ sst_status = psa_ps_set\(@@@001@@@, @@@003@@@_set_length, @@@003@@@_set_data,
+ PSA_STORAGE_FLAG_[A-Z_]+\);
+ 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/tf_fuzz/regression/000005_set_sst_rand_name_rand_data/template b/tf_fuzz/regression/000005_set_sst_rand_name_rand_data/template
new file mode 100644
index 0000000..5290f27
--- /dev/null
+++ b/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/tf_fuzz/regression/000006_set_sst_multi_name_rand_data/check.py b/tf_fuzz/regression/000006_set_sst_multi_name_rand_data/check.py
new file mode 100644
index 0000000..1bc5cbe
--- /dev/null
+++ b/tf_fuzz/regression/000006_set_sst_multi_name_rand_data/check.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+'''
+ Please read .../tf_fuzz/regression/README to understand this code.
+
+ Please also read the comments in .../tf_fuzz/regression/regress_lib/line_by_line.py.
+'''
+
+import sys, os, re, string, pdb
+sys.path.append ("../regress_lib")
+import line_by_line
+
+
+# Describe script usage:
+def usage():
+ print ('''
+ Command-line parameters:
+ 1. The test-template file, nominally named "template",
+ 2. The expected combined stdout/stderr output, nominally named "exp_stdout_stderr",
+ 3. The actual/generated combined stdout/stderr output, nominally named "stdout_stderr",
+ 4. The expected .c test file, nominally named "exp_test.c", and
+ 5. The actual, generated .c test file, nominally named "test.c".
+
+ Optionally, *before* these five arguments, you may add switches thus:
+ "--v" for verbose mode, to view line-by-line comparisons actual vs. expected,
+ "--q" to only print error messages and a successful-completion message,
+ "--qq" same as --q but not even printing out the completion message, and
+ "--s 12345" to run TF-Fuzz with seed value 12345 (or whatever).
+ ''')
+
+
+def main():
+ # See if we're supposed to be quiet:
+ loud = quiet = ultra_quiet = False
+ seed = ""
+ while sys.argv[1][0] == "-":
+ if sys.argv[1] == "--v":
+ loud = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--q":
+ quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--qq":
+ quiet = ultra_quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--s":
+ sys.argv.pop(1)
+ seed = sys.argv[1]
+ sys.argv.pop(1)
+ if not seed.isnumeric():
+ print ('The --s seed argument was not a number.')
+ usage()
+ sys.exit(1)
+
+ # Run TF-Fuzz:
+ if not quiet: print ("Running TF-Fuzz... ")
+ os.system ('rm -f stdout_stderr test.c')
+ command = '../../tfz -v ./' + sys.argv[1] + ' ./' + sys.argv[5]
+ command += ' ' + seed + ' >' + sys.argv[3] + ' 2>&1'
+ if loud:
+ print (command)
+ if os.system (command) == 0:
+ if not quiet: print ("TF-Fuzz run complete.")
+ else:
+ print ('Could not run TF-Fuzz; please see stdout_stderr file.')
+ sys.exit(2)
+
+ # Attempt to open files indicated on command line:
+ if len(sys.argv) != 6:
+ message = '{} requires 5 command-line arguments. Exiting.'
+ print (message.format(sys.argv[0]), file=sys.stderr)
+ usage()
+ sys.exit(3)
+ template_file_name = sys.argv[1]
+ exp_stdout_file_name = sys.argv[2]
+ act_stdout_file_name = sys.argv[3]
+ exp_test_file_name = sys.argv[4]
+ act_test_file_name = sys.argv[5]
+
+ try:
+ template_file = open (template_file_name, 'rt')
+ exp_stdout_file = open (exp_stdout_file_name, 'rt')
+ act_stdout_file = open (act_stdout_file_name, 'rt')
+ exp_test_file = open (exp_test_file_name, 'rt')
+ act_test_file = open (act_test_file_name, 'rt')
+ except FileNotFoundError:
+ print ('One or more files could not be found.')
+ usage();
+ sys.exit(4)
+ except:
+ print ('Something went wrong trying to open the input files.')
+ usage();
+ sys.exit(5)
+ else:
+ message = '\nInput files:\n {},\n {},\n {},\n'
+ message += ' {}, and\n {}\nopened successfully.\n'
+ if not quiet:
+ print (message.format (template_file_name, exp_stdout_file_name,
+ act_stdout_file_name, exp_test_file_name, act_test_file_name))
+
+ # Check it all:
+ if not quiet: print ("\nChecking test C file: ", end="")
+ line_by_line.check_file ( exp_test_file, exp_test_file_name,
+ act_test_file, act_test_file_name,
+ loud, quiet, ultra_quiet )
+ if not quiet: print ("Checking stdout and stderr: ", end="")
+ line_by_line.check_file ( exp_stdout_file, exp_stdout_file_name,
+ act_stdout_file, act_stdout_file_name,
+ loud, quiet, ultra_quiet )
+
+ # Ran to completion normally, so pass:
+ if not ultra_quiet: print ("Regression test passed.")
+ sys.exit(0)
+
+if __name__ == "__main__": main()
diff --git a/tf_fuzz/regression/000006_set_sst_multi_name_rand_data/exp_stdout_stderr b/tf_fuzz/regression/000006_set_sst_multi_name_rand_data/exp_stdout_stderr
new file mode 100644
index 0000000..4e76308
--- /dev/null
+++ b/tf_fuzz/regression/000006_set_sst_multi_name_rand_data/exp_stdout_stderr
@@ -0,0 +1,34 @@
+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"
+Asset identifier list: "data"
+Create from random data
+Set SST command: "*"
+Appended to end of call sequence: SST-set call.
+Appended to end of call sequence: SST-set call.
+Appended to end of call sequence: SST-set call.
+Appended to end of call sequence: SST-set call.
+Appended to end of call sequence: SST-set call.
+Set command: "*"
+Command with no expect: ";"
+Lines: Line number 3.
+Lines: Line number 3.
+Call sequence generated.
+Simulating call sequence...
+Call sequence:
+ SST-set call for asset john
+ SST-set call for asset paul
+ SST-set call for asset george
+ SST-set call for asset and
+ SST-set call for asset ringo
+Writing test file, ./test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tf_fuzz/regression/000006_set_sst_multi_name_rand_data/exp_test.c b/tf_fuzz/regression/000006_set_sst_multi_name_rand_data/exp_test.c
new file mode 100644
index 0000000..84026ac
--- /dev/null
+++ b/tf_fuzz/regression/000006_set_sst_multi_name_rand_data/exp_test.c
@@ -0,0 +1,117 @@
+/*
+ * 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 "tfm_memory_utils.h"
+#include "psa/crypto.h"
+#include "psa/crypto_sizes.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;
+ /* Variables (etc.) to initialize and check PSA assets: */
+ static uint8_t john_set_data\[\] = "@@012@10@@[a-z\ ]*[\.\?\!]";
+ static uint32_t john_set_length = \d+;
+ static uint8_t paul_set_data\[\] = "@@013@10@@[a-z\ ]*[\.\?\!]";
+ static uint32_t paul_set_length = \d+;
+ static uint8_t george_set_data\[\] = "@@014@10@@[a-z\ ]*[\.\?\!]";
+ static uint32_t george_set_length = \d+;
+ static uint8_t and_set_data\[\] = "@@015@10@@[a-z\ ]*[\.\?\!]";
+ static uint32_t and_set_length = \d+;
+ static uint8_t ringo_set_data\[\] = "@@016@10@@[a-z\ ]*[\.\?\!]";
+ static uint32_t ringo_set_length = \d+;
+ (void)sst_status;
+ /* "void" to prevent unused-variable warning, since the variable may not
+ * be used in this particular test case.
+ */
+
+ 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");
+
+
+ /* PSA calls to test: */
+ /\* Creating SST asset "john," with data "@@012@10@@...". \*/
+ sst_status = psa_ps_set\(@@@001@@@, john_set_length, john_set_data,
+ PSA_STORAGE_FLAG_[A-Z_]+\);
+ 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_set_length, paul_set_data,
+ PSA_STORAGE_FLAG_[A-Z_]+\);
+ 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_set_length, george_set_data,
+ PSA_STORAGE_FLAG_[A-Z_]+\);
+ 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_set_length, and_set_data,
+ PSA_STORAGE_FLAG_[A-Z_]+\);
+ 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_set_length, ringo_set_data,
+ PSA_STORAGE_FLAG_[A-Z_]+\);
+ 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/tf_fuzz/regression/000006_set_sst_multi_name_rand_data/template b/tf_fuzz/regression/000006_set_sst_multi_name_rand_data/template
new file mode 100644
index 0000000..2e86d75
--- /dev/null
+++ b/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/tf_fuzz/regression/000007_set_sst_multi_uid_rand_data/check.py b/tf_fuzz/regression/000007_set_sst_multi_uid_rand_data/check.py
new file mode 100644
index 0000000..1bc5cbe
--- /dev/null
+++ b/tf_fuzz/regression/000007_set_sst_multi_uid_rand_data/check.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+'''
+ Please read .../tf_fuzz/regression/README to understand this code.
+
+ Please also read the comments in .../tf_fuzz/regression/regress_lib/line_by_line.py.
+'''
+
+import sys, os, re, string, pdb
+sys.path.append ("../regress_lib")
+import line_by_line
+
+
+# Describe script usage:
+def usage():
+ print ('''
+ Command-line parameters:
+ 1. The test-template file, nominally named "template",
+ 2. The expected combined stdout/stderr output, nominally named "exp_stdout_stderr",
+ 3. The actual/generated combined stdout/stderr output, nominally named "stdout_stderr",
+ 4. The expected .c test file, nominally named "exp_test.c", and
+ 5. The actual, generated .c test file, nominally named "test.c".
+
+ Optionally, *before* these five arguments, you may add switches thus:
+ "--v" for verbose mode, to view line-by-line comparisons actual vs. expected,
+ "--q" to only print error messages and a successful-completion message,
+ "--qq" same as --q but not even printing out the completion message, and
+ "--s 12345" to run TF-Fuzz with seed value 12345 (or whatever).
+ ''')
+
+
+def main():
+ # See if we're supposed to be quiet:
+ loud = quiet = ultra_quiet = False
+ seed = ""
+ while sys.argv[1][0] == "-":
+ if sys.argv[1] == "--v":
+ loud = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--q":
+ quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--qq":
+ quiet = ultra_quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--s":
+ sys.argv.pop(1)
+ seed = sys.argv[1]
+ sys.argv.pop(1)
+ if not seed.isnumeric():
+ print ('The --s seed argument was not a number.')
+ usage()
+ sys.exit(1)
+
+ # Run TF-Fuzz:
+ if not quiet: print ("Running TF-Fuzz... ")
+ os.system ('rm -f stdout_stderr test.c')
+ command = '../../tfz -v ./' + sys.argv[1] + ' ./' + sys.argv[5]
+ command += ' ' + seed + ' >' + sys.argv[3] + ' 2>&1'
+ if loud:
+ print (command)
+ if os.system (command) == 0:
+ if not quiet: print ("TF-Fuzz run complete.")
+ else:
+ print ('Could not run TF-Fuzz; please see stdout_stderr file.')
+ sys.exit(2)
+
+ # Attempt to open files indicated on command line:
+ if len(sys.argv) != 6:
+ message = '{} requires 5 command-line arguments. Exiting.'
+ print (message.format(sys.argv[0]), file=sys.stderr)
+ usage()
+ sys.exit(3)
+ template_file_name = sys.argv[1]
+ exp_stdout_file_name = sys.argv[2]
+ act_stdout_file_name = sys.argv[3]
+ exp_test_file_name = sys.argv[4]
+ act_test_file_name = sys.argv[5]
+
+ try:
+ template_file = open (template_file_name, 'rt')
+ exp_stdout_file = open (exp_stdout_file_name, 'rt')
+ act_stdout_file = open (act_stdout_file_name, 'rt')
+ exp_test_file = open (exp_test_file_name, 'rt')
+ act_test_file = open (act_test_file_name, 'rt')
+ except FileNotFoundError:
+ print ('One or more files could not be found.')
+ usage();
+ sys.exit(4)
+ except:
+ print ('Something went wrong trying to open the input files.')
+ usage();
+ sys.exit(5)
+ else:
+ message = '\nInput files:\n {},\n {},\n {},\n'
+ message += ' {}, and\n {}\nopened successfully.\n'
+ if not quiet:
+ print (message.format (template_file_name, exp_stdout_file_name,
+ act_stdout_file_name, exp_test_file_name, act_test_file_name))
+
+ # Check it all:
+ if not quiet: print ("\nChecking test C file: ", end="")
+ line_by_line.check_file ( exp_test_file, exp_test_file_name,
+ act_test_file, act_test_file_name,
+ loud, quiet, ultra_quiet )
+ if not quiet: print ("Checking stdout and stderr: ", end="")
+ line_by_line.check_file ( exp_stdout_file, exp_stdout_file_name,
+ act_stdout_file, act_stdout_file_name,
+ loud, quiet, ultra_quiet )
+
+ # Ran to completion normally, so pass:
+ if not ultra_quiet: print ("Regression test passed.")
+ sys.exit(0)
+
+if __name__ == "__main__": main()
diff --git a/tf_fuzz/regression/000007_set_sst_multi_uid_rand_data/exp_stdout_stderr b/tf_fuzz/regression/000007_set_sst_multi_uid_rand_data/exp_stdout_stderr
new file mode 100644
index 0000000..5e9e362
--- /dev/null
+++ b/tf_fuzz/regression/000007_set_sst_multi_uid_rand_data/exp_stdout_stderr
@@ -0,0 +1,37 @@
+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"
+Create from random data
+Set SST command: "*"
+Appended to end of call sequence: SST-set call.
+Appended to end of call sequence: SST-set call.
+Appended to end of call sequence: SST-set call.
+Appended to end of call sequence: SST-set call.
+Appended to end of call sequence: SST-set call.
+Appended to end of call sequence: SST-set call.
+Set command: "*"
+Command with no expect: ";"
+Lines: Line number 3.
+Lines: Line number 3.
+Call sequence generated.
+Simulating call sequence...
+Call sequence:
+ SST-set call for asset SST_ID_17
+ SST-set call for asset SST_ID_19
+ SST-set call for asset SST_ID_24
+ SST-set call for asset SST_ID_31
+ SST-set call for asset SST_ID_34
+ SST-set call for asset SST_ID_41
+Writing test file, ./test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tf_fuzz/regression/000007_set_sst_multi_uid_rand_data/exp_test.c b/tf_fuzz/regression/000007_set_sst_multi_uid_rand_data/exp_test.c
new file mode 100644
index 0000000..02055e8
--- /dev/null
+++ b/tf_fuzz/regression/000007_set_sst_multi_uid_rand_data/exp_test.c
@@ -0,0 +1,131 @@
+/*
+ * 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 "tfm_memory_utils.h"
+#include "psa/crypto.h"
+#include "psa/crypto_sizes.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;
+ /* Variables (etc.) to initialize and check PSA assets: */
+ static uint8_t SST_ID_17_set_data\[\] = "@@012@10@@[a-z\ ]*[\.\?\!]";
+ static uint32_t SST_ID_17_set_length = \d+;
+ static uint8_t SST_ID_19_set_data\[\] = "@@013@10@@[a-z\ ]*[\.\?\!]";
+ static uint32_t SST_ID_19_set_length = \d+;
+ static uint8_t SST_ID_24_set_data\[\] = "@@014@10@@[a-z\ ]*[\.\?\!]";
+ static uint32_t SST_ID_24_set_length = \d+;
+ static uint8_t SST_ID_31_set_data\[\] = "@@015@10@@[a-z\ ]*[\.\?\!]";
+ static uint32_t SST_ID_31_set_length = \d+;
+ static uint8_t SST_ID_34_set_data\[\] = "@@016@10@@[a-z\ ]*[\.\?\!]";
+ static uint32_t SST_ID_34_set_length = \d+;
+ static uint8_t SST_ID_41_set_data\[\] = "@@017@10@@[a-z\ ]*[\.\?\!]";
+ static uint32_t SST_ID_41_set_length = \d+;
+ (void)sst_status;
+ /* "void" to prevent unused-variable warning, since the variable may not
+ * be used in this particular test case.
+ */
+
+ crypto_status = psa_crypto_init();
+ if (crypto_status != PSA_SUCCESS) {
+ TEST_FAIL("Could not initialize Crypto.");
+ return;
+ }
+
+ TEST_LOG("Test same with UIDs");
+
+
+ /* PSA calls to test: */
+ /\* Creating SST asset UID = 17 with data "@@012@10@@...". \*/
+ sst_status = psa_ps_set(17, SST_ID_17_set_length, SST_ID_17_set_data,
+ PSA_STORAGE_FLAG_[A-Z_]+\);
+ 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_set_length, SST_ID_19_set_data,
+ PSA_STORAGE_FLAG_[A-Z_]+\);
+ 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_set_length, SST_ID_24_set_data,
+ PSA_STORAGE_FLAG_[A-Z_]+\);
+ 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_set_length, SST_ID_31_set_data,
+ PSA_STORAGE_FLAG_[A-Z_]+\);
+ 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_set_length, SST_ID_34_set_data,
+ PSA_STORAGE_FLAG_[A-Z_]+\);
+ 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_set_length, SST_ID_41_set_data,
+ PSA_STORAGE_FLAG_[A-Z_]+\);
+ 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/tf_fuzz/regression/000007_set_sst_multi_uid_rand_data/template b/tf_fuzz/regression/000007_set_sst_multi_uid_rand_data/template
new file mode 100644
index 0000000..903027e
--- /dev/null
+++ b/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/tf_fuzz/regression/000008_set_sst_name_rand_data_read_check_wrong/check.py b/tf_fuzz/regression/000008_set_sst_name_rand_data_read_check_wrong/check.py
new file mode 100644
index 0000000..1bc5cbe
--- /dev/null
+++ b/tf_fuzz/regression/000008_set_sst_name_rand_data_read_check_wrong/check.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+'''
+ Please read .../tf_fuzz/regression/README to understand this code.
+
+ Please also read the comments in .../tf_fuzz/regression/regress_lib/line_by_line.py.
+'''
+
+import sys, os, re, string, pdb
+sys.path.append ("../regress_lib")
+import line_by_line
+
+
+# Describe script usage:
+def usage():
+ print ('''
+ Command-line parameters:
+ 1. The test-template file, nominally named "template",
+ 2. The expected combined stdout/stderr output, nominally named "exp_stdout_stderr",
+ 3. The actual/generated combined stdout/stderr output, nominally named "stdout_stderr",
+ 4. The expected .c test file, nominally named "exp_test.c", and
+ 5. The actual, generated .c test file, nominally named "test.c".
+
+ Optionally, *before* these five arguments, you may add switches thus:
+ "--v" for verbose mode, to view line-by-line comparisons actual vs. expected,
+ "--q" to only print error messages and a successful-completion message,
+ "--qq" same as --q but not even printing out the completion message, and
+ "--s 12345" to run TF-Fuzz with seed value 12345 (or whatever).
+ ''')
+
+
+def main():
+ # See if we're supposed to be quiet:
+ loud = quiet = ultra_quiet = False
+ seed = ""
+ while sys.argv[1][0] == "-":
+ if sys.argv[1] == "--v":
+ loud = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--q":
+ quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--qq":
+ quiet = ultra_quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--s":
+ sys.argv.pop(1)
+ seed = sys.argv[1]
+ sys.argv.pop(1)
+ if not seed.isnumeric():
+ print ('The --s seed argument was not a number.')
+ usage()
+ sys.exit(1)
+
+ # Run TF-Fuzz:
+ if not quiet: print ("Running TF-Fuzz... ")
+ os.system ('rm -f stdout_stderr test.c')
+ command = '../../tfz -v ./' + sys.argv[1] + ' ./' + sys.argv[5]
+ command += ' ' + seed + ' >' + sys.argv[3] + ' 2>&1'
+ if loud:
+ print (command)
+ if os.system (command) == 0:
+ if not quiet: print ("TF-Fuzz run complete.")
+ else:
+ print ('Could not run TF-Fuzz; please see stdout_stderr file.')
+ sys.exit(2)
+
+ # Attempt to open files indicated on command line:
+ if len(sys.argv) != 6:
+ message = '{} requires 5 command-line arguments. Exiting.'
+ print (message.format(sys.argv[0]), file=sys.stderr)
+ usage()
+ sys.exit(3)
+ template_file_name = sys.argv[1]
+ exp_stdout_file_name = sys.argv[2]
+ act_stdout_file_name = sys.argv[3]
+ exp_test_file_name = sys.argv[4]
+ act_test_file_name = sys.argv[5]
+
+ try:
+ template_file = open (template_file_name, 'rt')
+ exp_stdout_file = open (exp_stdout_file_name, 'rt')
+ act_stdout_file = open (act_stdout_file_name, 'rt')
+ exp_test_file = open (exp_test_file_name, 'rt')
+ act_test_file = open (act_test_file_name, 'rt')
+ except FileNotFoundError:
+ print ('One or more files could not be found.')
+ usage();
+ sys.exit(4)
+ except:
+ print ('Something went wrong trying to open the input files.')
+ usage();
+ sys.exit(5)
+ else:
+ message = '\nInput files:\n {},\n {},\n {},\n'
+ message += ' {}, and\n {}\nopened successfully.\n'
+ if not quiet:
+ print (message.format (template_file_name, exp_stdout_file_name,
+ act_stdout_file_name, exp_test_file_name, act_test_file_name))
+
+ # Check it all:
+ if not quiet: print ("\nChecking test C file: ", end="")
+ line_by_line.check_file ( exp_test_file, exp_test_file_name,
+ act_test_file, act_test_file_name,
+ loud, quiet, ultra_quiet )
+ if not quiet: print ("Checking stdout and stderr: ", end="")
+ line_by_line.check_file ( exp_stdout_file, exp_stdout_file_name,
+ act_stdout_file, act_stdout_file_name,
+ loud, quiet, ultra_quiet )
+
+ # Ran to completion normally, so pass:
+ if not ultra_quiet: print ("Regression test passed.")
+ sys.exit(0)
+
+if __name__ == "__main__": main()
diff --git a/tf_fuzz/regression/000008_set_sst_name_rand_data_read_check_wrong/exp_stdout_stderr b/tf_fuzz/regression/000008_set_sst_name_rand_data_read_check_wrong/exp_stdout_stderr
new file mode 100644
index 0000000..a138dc4
--- /dev/null
+++ b/tf_fuzz/regression/000008_set_sst_name_rand_data_read_check_wrong/exp_stdout_stderr
@@ -0,0 +1,34 @@
+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"
+Asset identifier list: "data"
+Create from random data
+Set SST command: ";"
+Appended to end of call sequence: SST-set call.
+Set command: ";"
+Command with no expect: ";"
+ASSET_IDENTIFIER: "snortwaggle"
+Asset identifier list: "check"
+LITERAL string: "almost certainly not *this*"
+Read check against literal: "almost certainly not *this*"
+SST-read arguments: expect"
+Read SST command: "expect"
+Appended to end of call sequence: SST-get call.
+Read command: "expect"
+Expect fail clause: "fail"
+Command with expect: ";"
+Lines: Line number 4.
+Lines: Line number 4.
+Lines: Line number 4.
+Call sequence generated.
+Simulating call sequence...
+Call sequence:
+ SST-set call for asset snortwaggle
+ SST-get call for asset snortwaggle
+Writing test file, ./test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tf_fuzz/regression/000008_set_sst_name_rand_data_read_check_wrong/exp_test.c b/tf_fuzz/regression/000008_set_sst_name_rand_data_read_check_wrong/exp_test.c
new file mode 100644
index 0000000..5f8486c
--- /dev/null
+++ b/tf_fuzz/regression/000008_set_sst_name_rand_data_read_check_wrong/exp_test.c
@@ -0,0 +1,76 @@
+/*
+ * 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 "tfm_memory_utils.h"
+#include "psa/crypto.h"
+#include "psa/crypto_sizes.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;
+ /* Variables (etc.) to initialize and check PSA assets: */
+ static uint8_t snortwaggle_set_data\[\] = "@@002@10@@[a-z\ ]*[\.\?\!]";
+ static uint32_t snortwaggle_set_length = \d+;
+ static uint8_t snortwaggle_exp_data[] = "almost certainly not *this*";
+ static uint8_t snortwaggle_act_data\[2048\] = "[A-Z][a-z ]*[\.\?\!]";
+ static size_t snortwaggle_act_length = \d+;
+ (void)sst_status;
+ /* "void" to prevent unused-variable warning, since the variable may not
+ * be used in this particular test case.
+ */
+
+ 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");
+
+
+ /* PSA calls to test: */
+ /\* Creating SST asset "snortwaggle," with data "@@002@10@@...". \*/
+ sst_status = psa_ps_set\(@@@001@@@, snortwaggle_set_length, snortwaggle_set_data,
+ PSA_STORAGE_FLAG_[A-Z_]+\);
+ if (sst_status != PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+ return;
+ }
+ sst_status = psa_ps_get\(@@@001@@@, 0, @@@003@@@, snortwaggle_act_data
+ &snortwaggle_act_length);
+ if (sst_status == PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_get() expected not PSA_SUCCESS.");
+ return;
+ }
+ /* Check that the data is correct */
+ if \(tfm_memcmp\(snortwaggle_act_data, snortwaggle_exp_data,
+ snortwaggle_act_length\) != 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/tf_fuzz/regression/000008_set_sst_name_rand_data_read_check_wrong/template b/tf_fuzz/regression/000008_set_sst_name_rand_data_read_check_wrong/template
new file mode 100644
index 0000000..03b22d9
--- /dev/null
+++ b/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*" expect fail;
diff --git a/tf_fuzz/regression/000009_set_sst_name_rand_data_read_check_var_read_print/check.py b/tf_fuzz/regression/000009_set_sst_name_rand_data_read_check_var_read_print/check.py
new file mode 100644
index 0000000..1bc5cbe
--- /dev/null
+++ b/tf_fuzz/regression/000009_set_sst_name_rand_data_read_check_var_read_print/check.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+'''
+ Please read .../tf_fuzz/regression/README to understand this code.
+
+ Please also read the comments in .../tf_fuzz/regression/regress_lib/line_by_line.py.
+'''
+
+import sys, os, re, string, pdb
+sys.path.append ("../regress_lib")
+import line_by_line
+
+
+# Describe script usage:
+def usage():
+ print ('''
+ Command-line parameters:
+ 1. The test-template file, nominally named "template",
+ 2. The expected combined stdout/stderr output, nominally named "exp_stdout_stderr",
+ 3. The actual/generated combined stdout/stderr output, nominally named "stdout_stderr",
+ 4. The expected .c test file, nominally named "exp_test.c", and
+ 5. The actual, generated .c test file, nominally named "test.c".
+
+ Optionally, *before* these five arguments, you may add switches thus:
+ "--v" for verbose mode, to view line-by-line comparisons actual vs. expected,
+ "--q" to only print error messages and a successful-completion message,
+ "--qq" same as --q but not even printing out the completion message, and
+ "--s 12345" to run TF-Fuzz with seed value 12345 (or whatever).
+ ''')
+
+
+def main():
+ # See if we're supposed to be quiet:
+ loud = quiet = ultra_quiet = False
+ seed = ""
+ while sys.argv[1][0] == "-":
+ if sys.argv[1] == "--v":
+ loud = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--q":
+ quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--qq":
+ quiet = ultra_quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--s":
+ sys.argv.pop(1)
+ seed = sys.argv[1]
+ sys.argv.pop(1)
+ if not seed.isnumeric():
+ print ('The --s seed argument was not a number.')
+ usage()
+ sys.exit(1)
+
+ # Run TF-Fuzz:
+ if not quiet: print ("Running TF-Fuzz... ")
+ os.system ('rm -f stdout_stderr test.c')
+ command = '../../tfz -v ./' + sys.argv[1] + ' ./' + sys.argv[5]
+ command += ' ' + seed + ' >' + sys.argv[3] + ' 2>&1'
+ if loud:
+ print (command)
+ if os.system (command) == 0:
+ if not quiet: print ("TF-Fuzz run complete.")
+ else:
+ print ('Could not run TF-Fuzz; please see stdout_stderr file.')
+ sys.exit(2)
+
+ # Attempt to open files indicated on command line:
+ if len(sys.argv) != 6:
+ message = '{} requires 5 command-line arguments. Exiting.'
+ print (message.format(sys.argv[0]), file=sys.stderr)
+ usage()
+ sys.exit(3)
+ template_file_name = sys.argv[1]
+ exp_stdout_file_name = sys.argv[2]
+ act_stdout_file_name = sys.argv[3]
+ exp_test_file_name = sys.argv[4]
+ act_test_file_name = sys.argv[5]
+
+ try:
+ template_file = open (template_file_name, 'rt')
+ exp_stdout_file = open (exp_stdout_file_name, 'rt')
+ act_stdout_file = open (act_stdout_file_name, 'rt')
+ exp_test_file = open (exp_test_file_name, 'rt')
+ act_test_file = open (act_test_file_name, 'rt')
+ except FileNotFoundError:
+ print ('One or more files could not be found.')
+ usage();
+ sys.exit(4)
+ except:
+ print ('Something went wrong trying to open the input files.')
+ usage();
+ sys.exit(5)
+ else:
+ message = '\nInput files:\n {},\n {},\n {},\n'
+ message += ' {}, and\n {}\nopened successfully.\n'
+ if not quiet:
+ print (message.format (template_file_name, exp_stdout_file_name,
+ act_stdout_file_name, exp_test_file_name, act_test_file_name))
+
+ # Check it all:
+ if not quiet: print ("\nChecking test C file: ", end="")
+ line_by_line.check_file ( exp_test_file, exp_test_file_name,
+ act_test_file, act_test_file_name,
+ loud, quiet, ultra_quiet )
+ if not quiet: print ("Checking stdout and stderr: ", end="")
+ line_by_line.check_file ( exp_stdout_file, exp_stdout_file_name,
+ act_stdout_file, act_stdout_file_name,
+ loud, quiet, ultra_quiet )
+
+ # Ran to completion normally, so pass:
+ if not ultra_quiet: print ("Regression test passed.")
+ sys.exit(0)
+
+if __name__ == "__main__": main()
diff --git a/tf_fuzz/regression/000009_set_sst_name_rand_data_read_check_var_read_print/exp_stdout_stderr b/tf_fuzz/regression/000009_set_sst_name_rand_data_read_check_var_read_print/exp_stdout_stderr
new file mode 100644
index 0000000..844cb17
--- /dev/null
+++ b/tf_fuzz/regression/000009_set_sst_name_rand_data_read_check_var_read_print/exp_stdout_stderr
@@ -0,0 +1,44 @@
+Trusted Firmware Fuzzer (TF-Fuzz) starting...
+
+Info: random seed was not specified.
+
+Using seed value of \d+ \(0x[a-f\d]+\).
+Purpose line: to check against a variable or dump into the log
+ASSET_IDENTIFIER: "greebledorf"
+Asset identifier list: "data"
+Create from random data
+Set SST command: ";"
+Appended to end of call sequence: SST-set call.
+Set command: ";"
+Command with no expect: ";"
+ASSET_IDENTIFIER: "greebledorf"
+Asset identifier list: "chk"
+IDENTIFIER: "a_variable"
+Read-arguments variable name: "a_variable"
+Read check against variable: "a_variable"
+SST-read arguments: ;"
+Read SST command: ";"
+Appended to end of call sequence: SST-get call.
+Read command: ";"
+Command with no expect: ";"
+ASSET_IDENTIFIER: "greebledorf"
+Asset identifier list: "print"
+Read log to test log: "print"
+SST-read arguments: ;"
+Read SST command: ";"
+Appended to end of call sequence: SST-get call.
+Read command: ";"
+Command with no expect: ";"
+Lines: Line number 5.
+Lines: Line number 5.
+Lines: Line number 5.
+Lines: Line number 5.
+Call sequence generated.
+Simulating call sequence...
+Call sequence:
+ SST-set call for asset greebledorf
+ SST-get call for asset greebledorf
+ SST-get call for asset greebledorf
+Writing test file, ./test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tf_fuzz/regression/000009_set_sst_name_rand_data_read_check_var_read_print/exp_test.c b/tf_fuzz/regression/000009_set_sst_name_rand_data_read_check_var_read_print/exp_test.c
new file mode 100644
index 0000000..f745c1f
--- /dev/null
+++ b/tf_fuzz/regression/000009_set_sst_name_rand_data_read_check_var_read_print/exp_test.c
@@ -0,0 +1,83 @@
+/*
+ * Test purpose:
+ * to check against a variable or dump into 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 "tfm_memory_utils.h"
+#include "psa/crypto.h"
+#include "psa/crypto_sizes.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;
+ /* Variables (etc.) to initialize and check PSA assets: */
+ static uint8_t greebledorf_set_data\[\] = "@@002@10@@[a-z\ ]*[\.\?\!]";
+ static uint32_t greebledorf_set_length = \d+;
+ static uint8_t a_variable_data\[\] = "[A-Z][a-z ]*[\.\?\!]";
+ static uint8_t greebledorf_act_data\[2048\] = "[A-Z][a-z ]*[\.\?\!]";
+ static size_t greebledorf_act_length = \d+;
+ (void)sst_status;
+ /* "void" to prevent unused-variable warning, since the variable may not
+ * be used in this particular test case.
+ */
+
+ crypto_status = psa_crypto_init();
+ if (crypto_status != PSA_SUCCESS) {
+ TEST_FAIL("Could not initialize Crypto.");
+ return;
+ }
+
+ TEST_LOG("Test to check against a variable or dump into the log");
+
+
+ /* PSA calls to test: */
+ /\* Creating SST asset "greebledorf," with data "@@002@10@@...". \*/
+ sst_status = psa_ps_set\(@@@001@@@, greebledorf_set_length, greebledorf_set_data,
+ PSA_STORAGE_FLAG_[A-Z_]+\);
+ if (sst_status != PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+ return;
+ }
+ sst_status = psa_ps_get\(@@@001@@@, 0, \d+, 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_data,
+ greebledorf_act_length) != 0) {
+ TEST_FAIL("Read data should be equal to result data");
+ return;
+ }
+ sst_status = psa_ps_get\(@@@001@@@, 0, \d+, 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/tf_fuzz/regression/000009_set_sst_name_rand_data_read_check_var_read_print/template b/tf_fuzz/regression/000009_set_sst_name_rand_data_read_check_var_read_print/template
new file mode 100644
index 0000000..a1a4d61
--- /dev/null
+++ b/tf_fuzz/regression/000009_set_sst_name_rand_data_read_check_var_read_print/template
@@ -0,0 +1,4 @@
+purpose to check against a variable or dump into the log;
+set sst name greebledorf data *;
+read sst name greebledorf chk a_variable;
+read sst name greebledorf print;
diff --git a/tf_fuzz/regression/000010_read_nonexistent_sst_check_string/check.py b/tf_fuzz/regression/000010_read_nonexistent_sst_check_string/check.py
new file mode 100644
index 0000000..1bc5cbe
--- /dev/null
+++ b/tf_fuzz/regression/000010_read_nonexistent_sst_check_string/check.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+'''
+ Please read .../tf_fuzz/regression/README to understand this code.
+
+ Please also read the comments in .../tf_fuzz/regression/regress_lib/line_by_line.py.
+'''
+
+import sys, os, re, string, pdb
+sys.path.append ("../regress_lib")
+import line_by_line
+
+
+# Describe script usage:
+def usage():
+ print ('''
+ Command-line parameters:
+ 1. The test-template file, nominally named "template",
+ 2. The expected combined stdout/stderr output, nominally named "exp_stdout_stderr",
+ 3. The actual/generated combined stdout/stderr output, nominally named "stdout_stderr",
+ 4. The expected .c test file, nominally named "exp_test.c", and
+ 5. The actual, generated .c test file, nominally named "test.c".
+
+ Optionally, *before* these five arguments, you may add switches thus:
+ "--v" for verbose mode, to view line-by-line comparisons actual vs. expected,
+ "--q" to only print error messages and a successful-completion message,
+ "--qq" same as --q but not even printing out the completion message, and
+ "--s 12345" to run TF-Fuzz with seed value 12345 (or whatever).
+ ''')
+
+
+def main():
+ # See if we're supposed to be quiet:
+ loud = quiet = ultra_quiet = False
+ seed = ""
+ while sys.argv[1][0] == "-":
+ if sys.argv[1] == "--v":
+ loud = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--q":
+ quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--qq":
+ quiet = ultra_quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--s":
+ sys.argv.pop(1)
+ seed = sys.argv[1]
+ sys.argv.pop(1)
+ if not seed.isnumeric():
+ print ('The --s seed argument was not a number.')
+ usage()
+ sys.exit(1)
+
+ # Run TF-Fuzz:
+ if not quiet: print ("Running TF-Fuzz... ")
+ os.system ('rm -f stdout_stderr test.c')
+ command = '../../tfz -v ./' + sys.argv[1] + ' ./' + sys.argv[5]
+ command += ' ' + seed + ' >' + sys.argv[3] + ' 2>&1'
+ if loud:
+ print (command)
+ if os.system (command) == 0:
+ if not quiet: print ("TF-Fuzz run complete.")
+ else:
+ print ('Could not run TF-Fuzz; please see stdout_stderr file.')
+ sys.exit(2)
+
+ # Attempt to open files indicated on command line:
+ if len(sys.argv) != 6:
+ message = '{} requires 5 command-line arguments. Exiting.'
+ print (message.format(sys.argv[0]), file=sys.stderr)
+ usage()
+ sys.exit(3)
+ template_file_name = sys.argv[1]
+ exp_stdout_file_name = sys.argv[2]
+ act_stdout_file_name = sys.argv[3]
+ exp_test_file_name = sys.argv[4]
+ act_test_file_name = sys.argv[5]
+
+ try:
+ template_file = open (template_file_name, 'rt')
+ exp_stdout_file = open (exp_stdout_file_name, 'rt')
+ act_stdout_file = open (act_stdout_file_name, 'rt')
+ exp_test_file = open (exp_test_file_name, 'rt')
+ act_test_file = open (act_test_file_name, 'rt')
+ except FileNotFoundError:
+ print ('One or more files could not be found.')
+ usage();
+ sys.exit(4)
+ except:
+ print ('Something went wrong trying to open the input files.')
+ usage();
+ sys.exit(5)
+ else:
+ message = '\nInput files:\n {},\n {},\n {},\n'
+ message += ' {}, and\n {}\nopened successfully.\n'
+ if not quiet:
+ print (message.format (template_file_name, exp_stdout_file_name,
+ act_stdout_file_name, exp_test_file_name, act_test_file_name))
+
+ # Check it all:
+ if not quiet: print ("\nChecking test C file: ", end="")
+ line_by_line.check_file ( exp_test_file, exp_test_file_name,
+ act_test_file, act_test_file_name,
+ loud, quiet, ultra_quiet )
+ if not quiet: print ("Checking stdout and stderr: ", end="")
+ line_by_line.check_file ( exp_stdout_file, exp_stdout_file_name,
+ act_stdout_file, act_stdout_file_name,
+ loud, quiet, ultra_quiet )
+
+ # Ran to completion normally, so pass:
+ if not ultra_quiet: print ("Regression test passed.")
+ sys.exit(0)
+
+if __name__ == "__main__": main()
diff --git a/tf_fuzz/regression/000010_read_nonexistent_sst_check_string/exp_stdout_stderr b/tf_fuzz/regression/000010_read_nonexistent_sst_check_string/exp_stdout_stderr
new file mode 100644
index 0000000..b8316fc
--- /dev/null
+++ b/tf_fuzz/regression/000010_read_nonexistent_sst_check_string/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 show what happens when you 'read' a non-existent asset
+ASSET_IDENTIFIER: "napoleon"
+Asset identifier list: "check"
+LITERAL string: "this won't work"
+Read check against literal: "this won't work"
+SST-read arguments: ;"
+Read SST command: ";"
+Appended to end of call sequence: SST-get call.
+Read command: ";"
+Command with no expect: ";"
+Lines: Line number 3.
+Lines: Line number 3.
+Call sequence generated.
+Simulating call sequence...
+Call sequence:
+ SST-get call for asset napoleon
+Writing test file, ./test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tf_fuzz/regression/000010_read_nonexistent_sst_check_string/exp_test.c b/tf_fuzz/regression/000010_read_nonexistent_sst_check_string/exp_test.c
new file mode 100644
index 0000000..2048a69
--- /dev/null
+++ b/tf_fuzz/regression/000010_read_nonexistent_sst_check_string/exp_test.c
@@ -0,0 +1,62 @@
+/*
+ * 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 "tfm_memory_utils.h"
+#include "psa/crypto.h"
+#include "psa/crypto_sizes.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;
+ /* 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\] = "[A-Z][a-z ]*[\.\?\!]";
+ static size_t napoleon_act_length = \d+;
+ (void)sst_status;
+ /* "void" to prevent unused-variable warning, since the variable may not
+ * be used in this particular test case.
+ */
+
+ 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");
+
+
+ /* PSA calls to test: */
+ sst_status = psa_ps_get\(\d+, 0, \d+, 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,
+ napoleon_act_length\) != 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/tf_fuzz/regression/000010_read_nonexistent_sst_check_string/template b/tf_fuzz/regression/000010_read_nonexistent_sst_check_string/template
new file mode 100644
index 0000000..3e70099
--- /dev/null
+++ b/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/tf_fuzz/regression/000011_read_nonexistent_sst_check_string_expect_pass/check.py b/tf_fuzz/regression/000011_read_nonexistent_sst_check_string_expect_pass/check.py
new file mode 100644
index 0000000..1bc5cbe
--- /dev/null
+++ b/tf_fuzz/regression/000011_read_nonexistent_sst_check_string_expect_pass/check.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+'''
+ Please read .../tf_fuzz/regression/README to understand this code.
+
+ Please also read the comments in .../tf_fuzz/regression/regress_lib/line_by_line.py.
+'''
+
+import sys, os, re, string, pdb
+sys.path.append ("../regress_lib")
+import line_by_line
+
+
+# Describe script usage:
+def usage():
+ print ('''
+ Command-line parameters:
+ 1. The test-template file, nominally named "template",
+ 2. The expected combined stdout/stderr output, nominally named "exp_stdout_stderr",
+ 3. The actual/generated combined stdout/stderr output, nominally named "stdout_stderr",
+ 4. The expected .c test file, nominally named "exp_test.c", and
+ 5. The actual, generated .c test file, nominally named "test.c".
+
+ Optionally, *before* these five arguments, you may add switches thus:
+ "--v" for verbose mode, to view line-by-line comparisons actual vs. expected,
+ "--q" to only print error messages and a successful-completion message,
+ "--qq" same as --q but not even printing out the completion message, and
+ "--s 12345" to run TF-Fuzz with seed value 12345 (or whatever).
+ ''')
+
+
+def main():
+ # See if we're supposed to be quiet:
+ loud = quiet = ultra_quiet = False
+ seed = ""
+ while sys.argv[1][0] == "-":
+ if sys.argv[1] == "--v":
+ loud = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--q":
+ quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--qq":
+ quiet = ultra_quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--s":
+ sys.argv.pop(1)
+ seed = sys.argv[1]
+ sys.argv.pop(1)
+ if not seed.isnumeric():
+ print ('The --s seed argument was not a number.')
+ usage()
+ sys.exit(1)
+
+ # Run TF-Fuzz:
+ if not quiet: print ("Running TF-Fuzz... ")
+ os.system ('rm -f stdout_stderr test.c')
+ command = '../../tfz -v ./' + sys.argv[1] + ' ./' + sys.argv[5]
+ command += ' ' + seed + ' >' + sys.argv[3] + ' 2>&1'
+ if loud:
+ print (command)
+ if os.system (command) == 0:
+ if not quiet: print ("TF-Fuzz run complete.")
+ else:
+ print ('Could not run TF-Fuzz; please see stdout_stderr file.')
+ sys.exit(2)
+
+ # Attempt to open files indicated on command line:
+ if len(sys.argv) != 6:
+ message = '{} requires 5 command-line arguments. Exiting.'
+ print (message.format(sys.argv[0]), file=sys.stderr)
+ usage()
+ sys.exit(3)
+ template_file_name = sys.argv[1]
+ exp_stdout_file_name = sys.argv[2]
+ act_stdout_file_name = sys.argv[3]
+ exp_test_file_name = sys.argv[4]
+ act_test_file_name = sys.argv[5]
+
+ try:
+ template_file = open (template_file_name, 'rt')
+ exp_stdout_file = open (exp_stdout_file_name, 'rt')
+ act_stdout_file = open (act_stdout_file_name, 'rt')
+ exp_test_file = open (exp_test_file_name, 'rt')
+ act_test_file = open (act_test_file_name, 'rt')
+ except FileNotFoundError:
+ print ('One or more files could not be found.')
+ usage();
+ sys.exit(4)
+ except:
+ print ('Something went wrong trying to open the input files.')
+ usage();
+ sys.exit(5)
+ else:
+ message = '\nInput files:\n {},\n {},\n {},\n'
+ message += ' {}, and\n {}\nopened successfully.\n'
+ if not quiet:
+ print (message.format (template_file_name, exp_stdout_file_name,
+ act_stdout_file_name, exp_test_file_name, act_test_file_name))
+
+ # Check it all:
+ if not quiet: print ("\nChecking test C file: ", end="")
+ line_by_line.check_file ( exp_test_file, exp_test_file_name,
+ act_test_file, act_test_file_name,
+ loud, quiet, ultra_quiet )
+ if not quiet: print ("Checking stdout and stderr: ", end="")
+ line_by_line.check_file ( exp_stdout_file, exp_stdout_file_name,
+ act_stdout_file, act_stdout_file_name,
+ loud, quiet, ultra_quiet )
+
+ # Ran to completion normally, so pass:
+ if not ultra_quiet: print ("Regression test passed.")
+ sys.exit(0)
+
+if __name__ == "__main__": main()
diff --git a/tf_fuzz/regression/000011_read_nonexistent_sst_check_string_expect_pass/exp_stdout_stderr b/tf_fuzz/regression/000011_read_nonexistent_sst_check_string_expect_pass/exp_stdout_stderr
new file mode 100644
index 0000000..2a7d593
--- /dev/null
+++ b/tf_fuzz/regression/000011_read_nonexistent_sst_check_string_expect_pass/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 illustrate that you can override TF-Fuzz's expected result
+ASSET_IDENTIFIER: "napoleon"
+Asset identifier list: "chk"
+LITERAL string: "this won't work"
+Read check against literal: "this won't work"
+SST-read arguments: expect"
+Read SST command: "expect"
+Appended to end of call sequence: SST-get call.
+Read command: "expect"
+Expect pass clause: "pass"
+Command with expect: ";"
+Lines: Line number 3.
+Lines: Line number 3.
+Call sequence generated.
+Simulating call sequence...
+Call sequence:
+ SST-get call for asset napoleon
+Writing test file, ./test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tf_fuzz/regression/000011_read_nonexistent_sst_check_string_expect_pass/exp_test.c b/tf_fuzz/regression/000011_read_nonexistent_sst_check_string_expect_pass/exp_test.c
new file mode 100644
index 0000000..d5d3e40
--- /dev/null
+++ b/tf_fuzz/regression/000011_read_nonexistent_sst_check_string_expect_pass/exp_test.c
@@ -0,0 +1,62 @@
+/*
+ * 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 "tfm_memory_utils.h"
+#include "psa/crypto.h"
+#include "psa/crypto_sizes.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;
+ /* 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\] = "[A-Z][a-z ]*[\.\?\!]";
+ static size_t napoleon_act_length = \d+;
+ (void)sst_status;
+ /* "void" to prevent unused-variable warning, since the variable may not
+ * be used in this particular test case.
+ */
+
+ 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");
+
+
+ /* PSA calls to test: */
+ sst_status = psa_ps_get\(\d+, 0, @@@001@@@, 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,
+ napoleon_act_length\) != 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/tf_fuzz/regression/000011_read_nonexistent_sst_check_string_expect_pass/template b/tf_fuzz/regression/000011_read_nonexistent_sst_check_string_expect_pass/template
new file mode 100644
index 0000000..6372bad
--- /dev/null
+++ b/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 chk "this won't work" expect pass;
diff --git a/tf_fuzz/regression/000012_read_nonexistent_sst_check_string_expect_other/check.py b/tf_fuzz/regression/000012_read_nonexistent_sst_check_string_expect_other/check.py
new file mode 100644
index 0000000..1bc5cbe
--- /dev/null
+++ b/tf_fuzz/regression/000012_read_nonexistent_sst_check_string_expect_other/check.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+'''
+ Please read .../tf_fuzz/regression/README to understand this code.
+
+ Please also read the comments in .../tf_fuzz/regression/regress_lib/line_by_line.py.
+'''
+
+import sys, os, re, string, pdb
+sys.path.append ("../regress_lib")
+import line_by_line
+
+
+# Describe script usage:
+def usage():
+ print ('''
+ Command-line parameters:
+ 1. The test-template file, nominally named "template",
+ 2. The expected combined stdout/stderr output, nominally named "exp_stdout_stderr",
+ 3. The actual/generated combined stdout/stderr output, nominally named "stdout_stderr",
+ 4. The expected .c test file, nominally named "exp_test.c", and
+ 5. The actual, generated .c test file, nominally named "test.c".
+
+ Optionally, *before* these five arguments, you may add switches thus:
+ "--v" for verbose mode, to view line-by-line comparisons actual vs. expected,
+ "--q" to only print error messages and a successful-completion message,
+ "--qq" same as --q but not even printing out the completion message, and
+ "--s 12345" to run TF-Fuzz with seed value 12345 (or whatever).
+ ''')
+
+
+def main():
+ # See if we're supposed to be quiet:
+ loud = quiet = ultra_quiet = False
+ seed = ""
+ while sys.argv[1][0] == "-":
+ if sys.argv[1] == "--v":
+ loud = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--q":
+ quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--qq":
+ quiet = ultra_quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--s":
+ sys.argv.pop(1)
+ seed = sys.argv[1]
+ sys.argv.pop(1)
+ if not seed.isnumeric():
+ print ('The --s seed argument was not a number.')
+ usage()
+ sys.exit(1)
+
+ # Run TF-Fuzz:
+ if not quiet: print ("Running TF-Fuzz... ")
+ os.system ('rm -f stdout_stderr test.c')
+ command = '../../tfz -v ./' + sys.argv[1] + ' ./' + sys.argv[5]
+ command += ' ' + seed + ' >' + sys.argv[3] + ' 2>&1'
+ if loud:
+ print (command)
+ if os.system (command) == 0:
+ if not quiet: print ("TF-Fuzz run complete.")
+ else:
+ print ('Could not run TF-Fuzz; please see stdout_stderr file.')
+ sys.exit(2)
+
+ # Attempt to open files indicated on command line:
+ if len(sys.argv) != 6:
+ message = '{} requires 5 command-line arguments. Exiting.'
+ print (message.format(sys.argv[0]), file=sys.stderr)
+ usage()
+ sys.exit(3)
+ template_file_name = sys.argv[1]
+ exp_stdout_file_name = sys.argv[2]
+ act_stdout_file_name = sys.argv[3]
+ exp_test_file_name = sys.argv[4]
+ act_test_file_name = sys.argv[5]
+
+ try:
+ template_file = open (template_file_name, 'rt')
+ exp_stdout_file = open (exp_stdout_file_name, 'rt')
+ act_stdout_file = open (act_stdout_file_name, 'rt')
+ exp_test_file = open (exp_test_file_name, 'rt')
+ act_test_file = open (act_test_file_name, 'rt')
+ except FileNotFoundError:
+ print ('One or more files could not be found.')
+ usage();
+ sys.exit(4)
+ except:
+ print ('Something went wrong trying to open the input files.')
+ usage();
+ sys.exit(5)
+ else:
+ message = '\nInput files:\n {},\n {},\n {},\n'
+ message += ' {}, and\n {}\nopened successfully.\n'
+ if not quiet:
+ print (message.format (template_file_name, exp_stdout_file_name,
+ act_stdout_file_name, exp_test_file_name, act_test_file_name))
+
+ # Check it all:
+ if not quiet: print ("\nChecking test C file: ", end="")
+ line_by_line.check_file ( exp_test_file, exp_test_file_name,
+ act_test_file, act_test_file_name,
+ loud, quiet, ultra_quiet )
+ if not quiet: print ("Checking stdout and stderr: ", end="")
+ line_by_line.check_file ( exp_stdout_file, exp_stdout_file_name,
+ act_stdout_file, act_stdout_file_name,
+ loud, quiet, ultra_quiet )
+
+ # Ran to completion normally, so pass:
+ if not ultra_quiet: print ("Regression test passed.")
+ sys.exit(0)
+
+if __name__ == "__main__": main()
diff --git a/tf_fuzz/regression/000012_read_nonexistent_sst_check_string_expect_other/exp_stdout_stderr b/tf_fuzz/regression/000012_read_nonexistent_sst_check_string_expect_other/exp_stdout_stderr
new file mode 100644
index 0000000..44bc211
--- /dev/null
+++ b/tf_fuzz/regression/000012_read_nonexistent_sst_check_string_expect_other/exp_stdout_stderr
@@ -0,0 +1,26 @@
+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"
+Asset identifier list: "check"
+LITERAL string: "this won't work"
+Read check against literal: "this won't work"
+SST-read arguments: expect"
+Read SST command: "expect"
+Appended to end of call sequence: SST-get call.
+Read command: "expect"
+IDENTIFIER: "PSA_ERROR_GENERIC_ERROR"
+Expect error clause: "PSA_ERROR_GENERIC_ERROR"
+Command with expect: ";"
+Lines: Line number 3.
+Lines: Line number 3.
+Call sequence generated.
+Simulating call sequence...
+Call sequence:
+ SST-get call for asset napoleon
+Writing test file, ./test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tf_fuzz/regression/000012_read_nonexistent_sst_check_string_expect_other/exp_test.c b/tf_fuzz/regression/000012_read_nonexistent_sst_check_string_expect_other/exp_test.c
new file mode 100644
index 0000000..359dd8a
--- /dev/null
+++ b/tf_fuzz/regression/000012_read_nonexistent_sst_check_string_expect_other/exp_test.c
@@ -0,0 +1,62 @@
+/*
+ * 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 "tfm_memory_utils.h"
+#include "psa/crypto.h"
+#include "psa/crypto_sizes.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;
+ /* 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\] = "[A-Z][a-z ]*[\.\?\!]";
+ static size_t napoleon_act_length = \d+;
+ (void)sst_status;
+ /* "void" to prevent unused-variable warning, since the variable may not
+ * be used in this particular test case.
+ */
+
+ 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");
+
+
+ /* PSA calls to test: */
+ sst_status = psa_ps_get\(\d+, 0, @@@001@@@, 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,
+ napoleon_act_length\) != 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/tf_fuzz/regression/000012_read_nonexistent_sst_check_string_expect_other/template b/tf_fuzz/regression/000012_read_nonexistent_sst_check_string_expect_other/template
new file mode 100644
index 0000000..c7825c5
--- /dev/null
+++ b/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/tf_fuzz/regression/000013_set_sst_name_rand_data_remove_twice/check.py b/tf_fuzz/regression/000013_set_sst_name_rand_data_remove_twice/check.py
new file mode 100644
index 0000000..1bc5cbe
--- /dev/null
+++ b/tf_fuzz/regression/000013_set_sst_name_rand_data_remove_twice/check.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+'''
+ Please read .../tf_fuzz/regression/README to understand this code.
+
+ Please also read the comments in .../tf_fuzz/regression/regress_lib/line_by_line.py.
+'''
+
+import sys, os, re, string, pdb
+sys.path.append ("../regress_lib")
+import line_by_line
+
+
+# Describe script usage:
+def usage():
+ print ('''
+ Command-line parameters:
+ 1. The test-template file, nominally named "template",
+ 2. The expected combined stdout/stderr output, nominally named "exp_stdout_stderr",
+ 3. The actual/generated combined stdout/stderr output, nominally named "stdout_stderr",
+ 4. The expected .c test file, nominally named "exp_test.c", and
+ 5. The actual, generated .c test file, nominally named "test.c".
+
+ Optionally, *before* these five arguments, you may add switches thus:
+ "--v" for verbose mode, to view line-by-line comparisons actual vs. expected,
+ "--q" to only print error messages and a successful-completion message,
+ "--qq" same as --q but not even printing out the completion message, and
+ "--s 12345" to run TF-Fuzz with seed value 12345 (or whatever).
+ ''')
+
+
+def main():
+ # See if we're supposed to be quiet:
+ loud = quiet = ultra_quiet = False
+ seed = ""
+ while sys.argv[1][0] == "-":
+ if sys.argv[1] == "--v":
+ loud = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--q":
+ quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--qq":
+ quiet = ultra_quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--s":
+ sys.argv.pop(1)
+ seed = sys.argv[1]
+ sys.argv.pop(1)
+ if not seed.isnumeric():
+ print ('The --s seed argument was not a number.')
+ usage()
+ sys.exit(1)
+
+ # Run TF-Fuzz:
+ if not quiet: print ("Running TF-Fuzz... ")
+ os.system ('rm -f stdout_stderr test.c')
+ command = '../../tfz -v ./' + sys.argv[1] + ' ./' + sys.argv[5]
+ command += ' ' + seed + ' >' + sys.argv[3] + ' 2>&1'
+ if loud:
+ print (command)
+ if os.system (command) == 0:
+ if not quiet: print ("TF-Fuzz run complete.")
+ else:
+ print ('Could not run TF-Fuzz; please see stdout_stderr file.')
+ sys.exit(2)
+
+ # Attempt to open files indicated on command line:
+ if len(sys.argv) != 6:
+ message = '{} requires 5 command-line arguments. Exiting.'
+ print (message.format(sys.argv[0]), file=sys.stderr)
+ usage()
+ sys.exit(3)
+ template_file_name = sys.argv[1]
+ exp_stdout_file_name = sys.argv[2]
+ act_stdout_file_name = sys.argv[3]
+ exp_test_file_name = sys.argv[4]
+ act_test_file_name = sys.argv[5]
+
+ try:
+ template_file = open (template_file_name, 'rt')
+ exp_stdout_file = open (exp_stdout_file_name, 'rt')
+ act_stdout_file = open (act_stdout_file_name, 'rt')
+ exp_test_file = open (exp_test_file_name, 'rt')
+ act_test_file = open (act_test_file_name, 'rt')
+ except FileNotFoundError:
+ print ('One or more files could not be found.')
+ usage();
+ sys.exit(4)
+ except:
+ print ('Something went wrong trying to open the input files.')
+ usage();
+ sys.exit(5)
+ else:
+ message = '\nInput files:\n {},\n {},\n {},\n'
+ message += ' {}, and\n {}\nopened successfully.\n'
+ if not quiet:
+ print (message.format (template_file_name, exp_stdout_file_name,
+ act_stdout_file_name, exp_test_file_name, act_test_file_name))
+
+ # Check it all:
+ if not quiet: print ("\nChecking test C file: ", end="")
+ line_by_line.check_file ( exp_test_file, exp_test_file_name,
+ act_test_file, act_test_file_name,
+ loud, quiet, ultra_quiet )
+ if not quiet: print ("Checking stdout and stderr: ", end="")
+ line_by_line.check_file ( exp_stdout_file, exp_stdout_file_name,
+ act_stdout_file, act_stdout_file_name,
+ loud, quiet, ultra_quiet )
+
+ # Ran to completion normally, so pass:
+ if not ultra_quiet: print ("Regression test passed.")
+ sys.exit(0)
+
+if __name__ == "__main__": main()
diff --git a/tf_fuzz/regression/000013_set_sst_name_rand_data_remove_twice/exp_stdout_stderr b/tf_fuzz/regression/000013_set_sst_name_rand_data_remove_twice/exp_stdout_stderr
new file mode 100644
index 0000000..f10b04d
--- /dev/null
+++ b/tf_fuzz/regression/000013_set_sst_name_rand_data_remove_twice/exp_stdout_stderr
@@ -0,0 +1,38 @@
+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"
+Asset identifier list: "data"
+Create from random data
+Set SST command: ";"
+Appended to end of call sequence: SST-set call.
+Set command: ";"
+Command with no expect: ";"
+ASSET_IDENTIFIER: "george"
+Asset identifier list: ";"
+Remove SST command: ";"
+Appended to end of call sequence: SST-remove call.
+Remove command: ";"
+Command with no expect: ";"
+ASSET_IDENTIFIER: "george"
+Asset identifier list: ";"
+Remove SST command: ";"
+Appended to end of call sequence: SST-remove call.
+Remove command: ";"
+Command with no expect: ";"
+Lines: Line number 5.
+Lines: Line number 5.
+Lines: Line number 5.
+Lines: Line number 5.
+Call sequence generated.
+Simulating call sequence...
+Call sequence:
+ SST-set call for asset george
+ SST-remove call for asset george
+ SST-remove call for asset george
+Writing test file, ./test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tf_fuzz/regression/000013_set_sst_name_rand_data_remove_twice/exp_test.c b/tf_fuzz/regression/000013_set_sst_name_rand_data_remove_twice/exp_test.c
new file mode 100644
index 0000000..efc6bf1
--- /dev/null
+++ b/tf_fuzz/regression/000013_set_sst_name_rand_data_remove_twice/exp_test.c
@@ -0,0 +1,66 @@
+/*
+ * 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 "tfm_memory_utils.h"
+#include "psa/crypto.h"
+#include "psa/crypto_sizes.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;
+ /* Variables (etc.) to initialize and check PSA assets: */
+ static uint8_t george_set_data\[\] = "@@002@10@@[a-z\ ]*[\.\?\!]";
+ static uint32_t george_set_length = \d+;
+ (void)sst_status;
+ /* "void" to prevent unused-variable warning, since the variable may not
+ * be used in this particular test case.
+ */
+
+ crypto_status = psa_crypto_init();
+ if (crypto_status != PSA_SUCCESS) {
+ TEST_FAIL("Could not initialize Crypto.");
+ return;
+ }
+
+ TEST_LOG("Test to illustrate deleting assets");
+
+
+ /* PSA calls to test: */
+ /\* Creating SST asset "george," with data "@@002@10@@...". \*/
+ sst_status = psa_ps_set\(@@@001@@@, george_set_length, george_set_data,
+ PSA_STORAGE_FLAG_[A-Z_]+\);
+ 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/tf_fuzz/regression/000013_set_sst_name_rand_data_remove_twice/template b/tf_fuzz/regression/000013_set_sst_name_rand_data_remove_twice/template
new file mode 100644
index 0000000..7edb72e
--- /dev/null
+++ b/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;
+rm sst name george;
diff --git a/tf_fuzz/regression/000014_set_sst_name_rand_data_remove_other/check.py b/tf_fuzz/regression/000014_set_sst_name_rand_data_remove_other/check.py
new file mode 100644
index 0000000..1bc5cbe
--- /dev/null
+++ b/tf_fuzz/regression/000014_set_sst_name_rand_data_remove_other/check.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+'''
+ Please read .../tf_fuzz/regression/README to understand this code.
+
+ Please also read the comments in .../tf_fuzz/regression/regress_lib/line_by_line.py.
+'''
+
+import sys, os, re, string, pdb
+sys.path.append ("../regress_lib")
+import line_by_line
+
+
+# Describe script usage:
+def usage():
+ print ('''
+ Command-line parameters:
+ 1. The test-template file, nominally named "template",
+ 2. The expected combined stdout/stderr output, nominally named "exp_stdout_stderr",
+ 3. The actual/generated combined stdout/stderr output, nominally named "stdout_stderr",
+ 4. The expected .c test file, nominally named "exp_test.c", and
+ 5. The actual, generated .c test file, nominally named "test.c".
+
+ Optionally, *before* these five arguments, you may add switches thus:
+ "--v" for verbose mode, to view line-by-line comparisons actual vs. expected,
+ "--q" to only print error messages and a successful-completion message,
+ "--qq" same as --q but not even printing out the completion message, and
+ "--s 12345" to run TF-Fuzz with seed value 12345 (or whatever).
+ ''')
+
+
+def main():
+ # See if we're supposed to be quiet:
+ loud = quiet = ultra_quiet = False
+ seed = ""
+ while sys.argv[1][0] == "-":
+ if sys.argv[1] == "--v":
+ loud = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--q":
+ quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--qq":
+ quiet = ultra_quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--s":
+ sys.argv.pop(1)
+ seed = sys.argv[1]
+ sys.argv.pop(1)
+ if not seed.isnumeric():
+ print ('The --s seed argument was not a number.')
+ usage()
+ sys.exit(1)
+
+ # Run TF-Fuzz:
+ if not quiet: print ("Running TF-Fuzz... ")
+ os.system ('rm -f stdout_stderr test.c')
+ command = '../../tfz -v ./' + sys.argv[1] + ' ./' + sys.argv[5]
+ command += ' ' + seed + ' >' + sys.argv[3] + ' 2>&1'
+ if loud:
+ print (command)
+ if os.system (command) == 0:
+ if not quiet: print ("TF-Fuzz run complete.")
+ else:
+ print ('Could not run TF-Fuzz; please see stdout_stderr file.')
+ sys.exit(2)
+
+ # Attempt to open files indicated on command line:
+ if len(sys.argv) != 6:
+ message = '{} requires 5 command-line arguments. Exiting.'
+ print (message.format(sys.argv[0]), file=sys.stderr)
+ usage()
+ sys.exit(3)
+ template_file_name = sys.argv[1]
+ exp_stdout_file_name = sys.argv[2]
+ act_stdout_file_name = sys.argv[3]
+ exp_test_file_name = sys.argv[4]
+ act_test_file_name = sys.argv[5]
+
+ try:
+ template_file = open (template_file_name, 'rt')
+ exp_stdout_file = open (exp_stdout_file_name, 'rt')
+ act_stdout_file = open (act_stdout_file_name, 'rt')
+ exp_test_file = open (exp_test_file_name, 'rt')
+ act_test_file = open (act_test_file_name, 'rt')
+ except FileNotFoundError:
+ print ('One or more files could not be found.')
+ usage();
+ sys.exit(4)
+ except:
+ print ('Something went wrong trying to open the input files.')
+ usage();
+ sys.exit(5)
+ else:
+ message = '\nInput files:\n {},\n {},\n {},\n'
+ message += ' {}, and\n {}\nopened successfully.\n'
+ if not quiet:
+ print (message.format (template_file_name, exp_stdout_file_name,
+ act_stdout_file_name, exp_test_file_name, act_test_file_name))
+
+ # Check it all:
+ if not quiet: print ("\nChecking test C file: ", end="")
+ line_by_line.check_file ( exp_test_file, exp_test_file_name,
+ act_test_file, act_test_file_name,
+ loud, quiet, ultra_quiet )
+ if not quiet: print ("Checking stdout and stderr: ", end="")
+ line_by_line.check_file ( exp_stdout_file, exp_stdout_file_name,
+ act_stdout_file, act_stdout_file_name,
+ loud, quiet, ultra_quiet )
+
+ # Ran to completion normally, so pass:
+ if not ultra_quiet: print ("Regression test passed.")
+ sys.exit(0)
+
+if __name__ == "__main__": main()
diff --git a/tf_fuzz/regression/000014_set_sst_name_rand_data_remove_other/exp_stdout_stderr b/tf_fuzz/regression/000014_set_sst_name_rand_data_remove_other/exp_stdout_stderr
new file mode 100644
index 0000000..1c447b7
--- /dev/null
+++ b/tf_fuzz/regression/000014_set_sst_name_rand_data_remove_other/exp_stdout_stderr
@@ -0,0 +1,30 @@
+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"
+Asset identifier list: "data"
+Create from random data
+Set SST command: ";"
+Appended to end of call sequence: SST-set call.
+Set command: ";"
+Command with no expect: ";"
+ASSET_IDENTIFIER: "ringo"
+Asset identifier list: ";"
+Remove SST command: ";"
+Appended to end of call sequence: SST-remove call.
+Remove command: ";"
+Command with no expect: ";"
+Lines: Line number 4.
+Lines: Line number 4.
+Lines: Line number 4.
+Call sequence generated.
+Simulating call sequence...
+Call sequence:
+ SST-set call for asset george
+ SST-remove call for asset ringo
+Writing test file, ./test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tf_fuzz/regression/000014_set_sst_name_rand_data_remove_other/exp_test.c b/tf_fuzz/regression/000014_set_sst_name_rand_data_remove_other/exp_test.c
new file mode 100644
index 0000000..85d51bb
--- /dev/null
+++ b/tf_fuzz/regression/000014_set_sst_name_rand_data_remove_other/exp_test.c
@@ -0,0 +1,66 @@
+/*
+ * 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 "tfm_memory_utils.h"
+#include "psa/crypto.h"
+#include "psa/crypto_sizes.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;
+ /* Variables (etc.) to initialize and check PSA assets: */
+ static uint8_t george_set_data\[\] = "@@002@10@@[a-z\ ]*[\.\?\!]";
+ static uint32_t george_set_length = \d+;
+ (void)sst_status;
+ /* "void" to prevent unused-variable warning, since the variable may not
+ * be used in this particular test case.
+ */
+
+ 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");
+
+
+ /* PSA calls to test: */
+ /\* Creating SST asset "george," with data "@@002@10@@...". \*/
+ sst_status = psa_ps_set\(@@@001@@@, george_set_length, george_set_data,
+ PSA_STORAGE_FLAG_[A-Z_]+\);
+ if (sst_status != PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+ return;
+ }
+ sst_status = psa_ps_remove\(\d+\);
+ 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/tf_fuzz/regression/000014_set_sst_name_rand_data_remove_other/template b/tf_fuzz/regression/000014_set_sst_name_rand_data_remove_other/template
new file mode 100644
index 0000000..5b9485c
--- /dev/null
+++ b/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/tf_fuzz/regression/000015_set_sst_name_only/check.py b/tf_fuzz/regression/000015_set_sst_name_only/check.py
new file mode 100644
index 0000000..1bc5cbe
--- /dev/null
+++ b/tf_fuzz/regression/000015_set_sst_name_only/check.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+'''
+ Please read .../tf_fuzz/regression/README to understand this code.
+
+ Please also read the comments in .../tf_fuzz/regression/regress_lib/line_by_line.py.
+'''
+
+import sys, os, re, string, pdb
+sys.path.append ("../regress_lib")
+import line_by_line
+
+
+# Describe script usage:
+def usage():
+ print ('''
+ Command-line parameters:
+ 1. The test-template file, nominally named "template",
+ 2. The expected combined stdout/stderr output, nominally named "exp_stdout_stderr",
+ 3. The actual/generated combined stdout/stderr output, nominally named "stdout_stderr",
+ 4. The expected .c test file, nominally named "exp_test.c", and
+ 5. The actual, generated .c test file, nominally named "test.c".
+
+ Optionally, *before* these five arguments, you may add switches thus:
+ "--v" for verbose mode, to view line-by-line comparisons actual vs. expected,
+ "--q" to only print error messages and a successful-completion message,
+ "--qq" same as --q but not even printing out the completion message, and
+ "--s 12345" to run TF-Fuzz with seed value 12345 (or whatever).
+ ''')
+
+
+def main():
+ # See if we're supposed to be quiet:
+ loud = quiet = ultra_quiet = False
+ seed = ""
+ while sys.argv[1][0] == "-":
+ if sys.argv[1] == "--v":
+ loud = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--q":
+ quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--qq":
+ quiet = ultra_quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--s":
+ sys.argv.pop(1)
+ seed = sys.argv[1]
+ sys.argv.pop(1)
+ if not seed.isnumeric():
+ print ('The --s seed argument was not a number.')
+ usage()
+ sys.exit(1)
+
+ # Run TF-Fuzz:
+ if not quiet: print ("Running TF-Fuzz... ")
+ os.system ('rm -f stdout_stderr test.c')
+ command = '../../tfz -v ./' + sys.argv[1] + ' ./' + sys.argv[5]
+ command += ' ' + seed + ' >' + sys.argv[3] + ' 2>&1'
+ if loud:
+ print (command)
+ if os.system (command) == 0:
+ if not quiet: print ("TF-Fuzz run complete.")
+ else:
+ print ('Could not run TF-Fuzz; please see stdout_stderr file.')
+ sys.exit(2)
+
+ # Attempt to open files indicated on command line:
+ if len(sys.argv) != 6:
+ message = '{} requires 5 command-line arguments. Exiting.'
+ print (message.format(sys.argv[0]), file=sys.stderr)
+ usage()
+ sys.exit(3)
+ template_file_name = sys.argv[1]
+ exp_stdout_file_name = sys.argv[2]
+ act_stdout_file_name = sys.argv[3]
+ exp_test_file_name = sys.argv[4]
+ act_test_file_name = sys.argv[5]
+
+ try:
+ template_file = open (template_file_name, 'rt')
+ exp_stdout_file = open (exp_stdout_file_name, 'rt')
+ act_stdout_file = open (act_stdout_file_name, 'rt')
+ exp_test_file = open (exp_test_file_name, 'rt')
+ act_test_file = open (act_test_file_name, 'rt')
+ except FileNotFoundError:
+ print ('One or more files could not be found.')
+ usage();
+ sys.exit(4)
+ except:
+ print ('Something went wrong trying to open the input files.')
+ usage();
+ sys.exit(5)
+ else:
+ message = '\nInput files:\n {},\n {},\n {},\n'
+ message += ' {}, and\n {}\nopened successfully.\n'
+ if not quiet:
+ print (message.format (template_file_name, exp_stdout_file_name,
+ act_stdout_file_name, exp_test_file_name, act_test_file_name))
+
+ # Check it all:
+ if not quiet: print ("\nChecking test C file: ", end="")
+ line_by_line.check_file ( exp_test_file, exp_test_file_name,
+ act_test_file, act_test_file_name,
+ loud, quiet, ultra_quiet )
+ if not quiet: print ("Checking stdout and stderr: ", end="")
+ line_by_line.check_file ( exp_stdout_file, exp_stdout_file_name,
+ act_stdout_file, act_stdout_file_name,
+ loud, quiet, ultra_quiet )
+
+ # Ran to completion normally, so pass:
+ if not ultra_quiet: print ("Regression test passed.")
+ sys.exit(0)
+
+if __name__ == "__main__": main()
diff --git a/tf_fuzz/regression/000015_set_sst_name_only/exp_stdout_stderr b/tf_fuzz/regression/000015_set_sst_name_only/exp_stdout_stderr
new file mode 100644
index 0000000..318a125
--- /dev/null
+++ b/tf_fuzz/regression/000015_set_sst_name_only/exp_stdout_stderr
@@ -0,0 +1,30 @@
+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 if you don't have say anything about data to randomize it
+ASSET_IDENTIFIER: "random"
+Asset identifier list: ";"
+SST-create from random data (no 'data *')
+Set SST command: ";"
+Appended to end of call sequence: SST-set call.
+Set command: ";"
+Command with no expect: ";"
+Asset random identifier: "*"
+SST-create from random data (no 'data *')
+Set SST command: ";"
+Appended to end of call sequence: SST-set call.
+Set command: ";"
+Command with no expect: ";"
+Lines: Line number 4.
+Lines: Line number 4.
+Lines: Line number 4.
+Call sequence generated.
+Simulating call sequence...
+Call sequence:
+ SST-set call for asset random
+ SST-set call for asset [a-z]+
+Writing test file, ./test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tf_fuzz/regression/000015_set_sst_name_only/exp_test.c b/tf_fuzz/regression/000015_set_sst_name_only/exp_test.c
new file mode 100644
index 0000000..900d9e2
--- /dev/null
+++ b/tf_fuzz/regression/000015_set_sst_name_only/exp_test.c
@@ -0,0 +1,75 @@
+/*
+ * Test purpose:
+ * to show that if you don't have say anything about data to randomize it
+ *
+ */
+
+#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 "tfm_memory_utils.h"
+#include "psa/crypto.h"
+#include "psa/crypto_sizes.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;
+ /* Variables (etc.) to initialize and check PSA assets: */
+ static uint8_t random_set_data\[\] = "@@002@10@@[a-z\ ]*[\.\?\!]";
+ static uint32_t random_set_length = \d+;
+ static uint8_t @@@003@@@_set_data\[\] = "@@004@10@@[a-z\ ]*[\.\?\!]";
+ static uint32_t @@@003@@@_set_length = \d+;
+ (void)sst_status;
+ /* "void" to prevent unused-variable warning, since the variable may not
+ * be used in this particular test case.
+ */
+
+ crypto_status = psa_crypto_init();
+ if (crypto_status != PSA_SUCCESS) {
+ TEST_FAIL("Could not initialize Crypto.");
+ return;
+ }
+
+ TEST_LOG("Test to show that if you don't have say anything about data to randomize it");
+
+
+ /* PSA calls to test: */
+ /\* Creating SST asset "random," with data "@@002@10@@...". \*/
+ sst_status = psa_ps_set\(@@@001@@@, random_set_length, random_set_data,
+ PSA_STORAGE_FLAG_[A-Z_]+\);
+ if (sst_status != PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+ return;
+ }
+ /\* Creating SST asset "@@@003@@@," with data "@@004@10@@...". \*/
+ sst_status = psa_ps_set\(@@@004@@@, @@@003@@@_set_length, @@@003@@@_set_data,
+ PSA_STORAGE_FLAG_[A-Z_]+\);
+ 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\(@@@004@@@\);
+ 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/tf_fuzz/regression/000015_set_sst_name_only/template b/tf_fuzz/regression/000015_set_sst_name_only/template
new file mode 100644
index 0000000..63220db
--- /dev/null
+++ b/tf_fuzz/regression/000015_set_sst_name_only/template
@@ -0,0 +1,3 @@
+purpose to show that if you don't have say anything about data to randomize it;
+set sst name random;
+set sst name *;
diff --git a/tf_fuzz/regression/000016_set_sst_single_asset_set_multiple_times/check.py b/tf_fuzz/regression/000016_set_sst_single_asset_set_multiple_times/check.py
new file mode 100644
index 0000000..1bc5cbe
--- /dev/null
+++ b/tf_fuzz/regression/000016_set_sst_single_asset_set_multiple_times/check.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+'''
+ Please read .../tf_fuzz/regression/README to understand this code.
+
+ Please also read the comments in .../tf_fuzz/regression/regress_lib/line_by_line.py.
+'''
+
+import sys, os, re, string, pdb
+sys.path.append ("../regress_lib")
+import line_by_line
+
+
+# Describe script usage:
+def usage():
+ print ('''
+ Command-line parameters:
+ 1. The test-template file, nominally named "template",
+ 2. The expected combined stdout/stderr output, nominally named "exp_stdout_stderr",
+ 3. The actual/generated combined stdout/stderr output, nominally named "stdout_stderr",
+ 4. The expected .c test file, nominally named "exp_test.c", and
+ 5. The actual, generated .c test file, nominally named "test.c".
+
+ Optionally, *before* these five arguments, you may add switches thus:
+ "--v" for verbose mode, to view line-by-line comparisons actual vs. expected,
+ "--q" to only print error messages and a successful-completion message,
+ "--qq" same as --q but not even printing out the completion message, and
+ "--s 12345" to run TF-Fuzz with seed value 12345 (or whatever).
+ ''')
+
+
+def main():
+ # See if we're supposed to be quiet:
+ loud = quiet = ultra_quiet = False
+ seed = ""
+ while sys.argv[1][0] == "-":
+ if sys.argv[1] == "--v":
+ loud = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--q":
+ quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--qq":
+ quiet = ultra_quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--s":
+ sys.argv.pop(1)
+ seed = sys.argv[1]
+ sys.argv.pop(1)
+ if not seed.isnumeric():
+ print ('The --s seed argument was not a number.')
+ usage()
+ sys.exit(1)
+
+ # Run TF-Fuzz:
+ if not quiet: print ("Running TF-Fuzz... ")
+ os.system ('rm -f stdout_stderr test.c')
+ command = '../../tfz -v ./' + sys.argv[1] + ' ./' + sys.argv[5]
+ command += ' ' + seed + ' >' + sys.argv[3] + ' 2>&1'
+ if loud:
+ print (command)
+ if os.system (command) == 0:
+ if not quiet: print ("TF-Fuzz run complete.")
+ else:
+ print ('Could not run TF-Fuzz; please see stdout_stderr file.')
+ sys.exit(2)
+
+ # Attempt to open files indicated on command line:
+ if len(sys.argv) != 6:
+ message = '{} requires 5 command-line arguments. Exiting.'
+ print (message.format(sys.argv[0]), file=sys.stderr)
+ usage()
+ sys.exit(3)
+ template_file_name = sys.argv[1]
+ exp_stdout_file_name = sys.argv[2]
+ act_stdout_file_name = sys.argv[3]
+ exp_test_file_name = sys.argv[4]
+ act_test_file_name = sys.argv[5]
+
+ try:
+ template_file = open (template_file_name, 'rt')
+ exp_stdout_file = open (exp_stdout_file_name, 'rt')
+ act_stdout_file = open (act_stdout_file_name, 'rt')
+ exp_test_file = open (exp_test_file_name, 'rt')
+ act_test_file = open (act_test_file_name, 'rt')
+ except FileNotFoundError:
+ print ('One or more files could not be found.')
+ usage();
+ sys.exit(4)
+ except:
+ print ('Something went wrong trying to open the input files.')
+ usage();
+ sys.exit(5)
+ else:
+ message = '\nInput files:\n {},\n {},\n {},\n'
+ message += ' {}, and\n {}\nopened successfully.\n'
+ if not quiet:
+ print (message.format (template_file_name, exp_stdout_file_name,
+ act_stdout_file_name, exp_test_file_name, act_test_file_name))
+
+ # Check it all:
+ if not quiet: print ("\nChecking test C file: ", end="")
+ line_by_line.check_file ( exp_test_file, exp_test_file_name,
+ act_test_file, act_test_file_name,
+ loud, quiet, ultra_quiet )
+ if not quiet: print ("Checking stdout and stderr: ", end="")
+ line_by_line.check_file ( exp_stdout_file, exp_stdout_file_name,
+ act_stdout_file, act_stdout_file_name,
+ loud, quiet, ultra_quiet )
+
+ # Ran to completion normally, so pass:
+ if not ultra_quiet: print ("Regression test passed.")
+ sys.exit(0)
+
+if __name__ == "__main__": main()
diff --git a/tf_fuzz/regression/000016_set_sst_single_asset_set_multiple_times/exp_stdout_stderr b/tf_fuzz/regression/000016_set_sst_single_asset_set_multiple_times/exp_stdout_stderr
new file mode 100644
index 0000000..a85de7d
--- /dev/null
+++ b/tf_fuzz/regression/000016_set_sst_single_asset_set_multiple_times/exp_stdout_stderr
@@ -0,0 +1,66 @@
+Trusted Firmware Fuzzer (TF-Fuzz) starting...
+
+Info: random seed was not specified.
+
+Using seed value of \d+ \(0x[a-f\d]+\).
+Purpose line: to assign a sequence of values to a single asset
+ASSET_IDENTIFIER: "indecisive"
+Asset identifier list: "data"
+LITERAL string: "First value"
+Create from literal data: ""First value""
+SST no storage flag: none"
+SST creation flag
+;"
+SST creation flags
+;"
+Set SST command: ";"
+Appended to end of call sequence: SST-set call.
+Set command: ";"
+Command with no expect: ";"
+ASSET_IDENTIFIER: "indecisive"
+Asset identifier list: "data"
+LITERAL string: "Second value"
+Create from literal data: ""Second value""
+Set SST command: ";"
+Appended to end of call sequence: SST-set call.
+Set command: ";"
+Command with no expect: ";"
+ASSET_IDENTIFIER: "indecisive"
+Asset identifier list: "data"
+Create from random data
+Set SST command: ";"
+Appended to end of call sequence: SST-set call.
+Set command: ";"
+Command with no expect: ";"
+ASSET_IDENTIFIER: "indecisive"
+Asset identifier list: "data"
+LITERAL string: "Fourth value"
+Create from literal data: ""Fourth value""
+Set SST command: ";"
+Appended to end of call sequence: SST-set call.
+Set command: ";"
+Command with no expect: ";"
+ASSET_IDENTIFIER: "indecisive"
+Asset identifier list: "data"
+Create from random data
+Set SST command: ";"
+Appended to end of call sequence: SST-set call.
+Set command: ";"
+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.
+Call sequence generated.
+Simulating call sequence...
+Call sequence:
+ SST-set call for asset indecisive
+ SST-set call for asset indecisive
+ SST-set call for asset indecisive
+ SST-set call for asset indecisive
+ SST-set call for asset indecisive
+Writing test file, ./test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tf_fuzz/regression/000016_set_sst_single_asset_set_multiple_times/exp_test.c b/tf_fuzz/regression/000016_set_sst_single_asset_set_multiple_times/exp_test.c
new file mode 100644
index 0000000..224c85c
--- /dev/null
+++ b/tf_fuzz/regression/000016_set_sst_single_asset_set_multiple_times/exp_test.c
@@ -0,0 +1,97 @@
+/*
+ * Test purpose:
+ * to assign a sequence of values to a single 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 "tfm_memory_utils.h"
+#include "psa/crypto.h"
+#include "psa/crypto_sizes.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;
+ /* Variables (etc.) to initialize and check PSA assets: */
+ static uint8_t indecisive_set_data[] = "First value";
+ static uint32_t indecisive_set_length = 11;
+ static uint8_t indecisive_set_data_1[] = "Second value";
+ static uint32_t indecisive_set_length_1 = 12;
+ static uint8_t indecisive_set_data_2\[\] = "@@001@10@@[a-z\ ]*[\.\?\!]";
+ static uint32_t indecisive_set_length_2 = \d+;
+ static uint8_t indecisive_set_data_3[] = "Fourth value";
+ static uint32_t indecisive_set_length_3 = 12;
+ static uint8_t indecisive_set_data_4\[\] = "@@002@10@@[a-z\ ]*[\.\?\!]";
+ static uint32_t indecisive_set_length_4 = \d+;
+ (void)sst_status;
+ /* "void" to prevent unused-variable warning, since the variable may not
+ * be used in this particular test case.
+ */
+
+ crypto_status = psa_crypto_init();
+ if (crypto_status != PSA_SUCCESS) {
+ TEST_FAIL("Could not initialize Crypto.");
+ return;
+ }
+
+ TEST_LOG("Test to assign a sequence of values to a single asset");
+
+
+ /* PSA calls to test: */
+ /* Creating SST asset "indecisive," with data "First valu...". */
+ sst_status = psa_ps_set\(@@@001@@@, indecisive_set_length, indecisive_set_data,
+ PSA_STORAGE_FLAG_[A-Z_]+\);
+ if (sst_status != PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+ return;
+ }
+ /* Resetting SST asset "indecisive," with data "Second val...". */
+ sst_status = psa_ps_set\(@@@001@@@, indecisive_set_length_1, indecisive_set_data_1,
+ PSA_STORAGE_FLAG_[A-Z_]+\);
+ if (sst_status != PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+ return;
+ }
+ /\* Resetting SST asset "indecisive," with data "@@001@10@@...". \*/
+ sst_status = psa_ps_set\(@@@001@@@, indecisive_set_length_2, indecisive_set_data_2,
+ PSA_STORAGE_FLAG_[A-Z_]+\);
+ if (sst_status != PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+ return;
+ }
+ /* Resetting SST asset "indecisive," with data "Fourth val...". */
+ sst_status = psa_ps_set\(@@@001@@@, indecisive_set_length_3, indecisive_set_data_3,
+ PSA_STORAGE_FLAG_[A-Z_]+\);
+ if (sst_status != PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+ return;
+ }
+ /\* Resetting SST asset "indecisive," with data "@@002@10@@...". \*/
+ sst_status = psa_ps_set\(@@@001@@@, indecisive_set_length_4, indecisive_set_data_4,
+ PSA_STORAGE_FLAG_[A-Z_]+\);
+ 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/tf_fuzz/regression/000016_set_sst_single_asset_set_multiple_times/template b/tf_fuzz/regression/000016_set_sst_single_asset_set_multiple_times/template
new file mode 100644
index 0000000..0127a29
--- /dev/null
+++ b/tf_fuzz/regression/000016_set_sst_single_asset_set_multiple_times/template
@@ -0,0 +1,6 @@
+purpose to assign a sequence of values to a single asset;
+set sst name indecisive data "First value" flag none;
+set sst name indecisive data "Second value";
+set sst name indecisive data *;
+set sst name indecisive data "Fourth value";
+set sst name indecisive data *;
diff --git a/tf_fuzz/regression/000017_read_sst_check_single_asset_multiple_times/check.py b/tf_fuzz/regression/000017_read_sst_check_single_asset_multiple_times/check.py
new file mode 100644
index 0000000..1bc5cbe
--- /dev/null
+++ b/tf_fuzz/regression/000017_read_sst_check_single_asset_multiple_times/check.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+'''
+ Please read .../tf_fuzz/regression/README to understand this code.
+
+ Please also read the comments in .../tf_fuzz/regression/regress_lib/line_by_line.py.
+'''
+
+import sys, os, re, string, pdb
+sys.path.append ("../regress_lib")
+import line_by_line
+
+
+# Describe script usage:
+def usage():
+ print ('''
+ Command-line parameters:
+ 1. The test-template file, nominally named "template",
+ 2. The expected combined stdout/stderr output, nominally named "exp_stdout_stderr",
+ 3. The actual/generated combined stdout/stderr output, nominally named "stdout_stderr",
+ 4. The expected .c test file, nominally named "exp_test.c", and
+ 5. The actual, generated .c test file, nominally named "test.c".
+
+ Optionally, *before* these five arguments, you may add switches thus:
+ "--v" for verbose mode, to view line-by-line comparisons actual vs. expected,
+ "--q" to only print error messages and a successful-completion message,
+ "--qq" same as --q but not even printing out the completion message, and
+ "--s 12345" to run TF-Fuzz with seed value 12345 (or whatever).
+ ''')
+
+
+def main():
+ # See if we're supposed to be quiet:
+ loud = quiet = ultra_quiet = False
+ seed = ""
+ while sys.argv[1][0] == "-":
+ if sys.argv[1] == "--v":
+ loud = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--q":
+ quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--qq":
+ quiet = ultra_quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--s":
+ sys.argv.pop(1)
+ seed = sys.argv[1]
+ sys.argv.pop(1)
+ if not seed.isnumeric():
+ print ('The --s seed argument was not a number.')
+ usage()
+ sys.exit(1)
+
+ # Run TF-Fuzz:
+ if not quiet: print ("Running TF-Fuzz... ")
+ os.system ('rm -f stdout_stderr test.c')
+ command = '../../tfz -v ./' + sys.argv[1] + ' ./' + sys.argv[5]
+ command += ' ' + seed + ' >' + sys.argv[3] + ' 2>&1'
+ if loud:
+ print (command)
+ if os.system (command) == 0:
+ if not quiet: print ("TF-Fuzz run complete.")
+ else:
+ print ('Could not run TF-Fuzz; please see stdout_stderr file.')
+ sys.exit(2)
+
+ # Attempt to open files indicated on command line:
+ if len(sys.argv) != 6:
+ message = '{} requires 5 command-line arguments. Exiting.'
+ print (message.format(sys.argv[0]), file=sys.stderr)
+ usage()
+ sys.exit(3)
+ template_file_name = sys.argv[1]
+ exp_stdout_file_name = sys.argv[2]
+ act_stdout_file_name = sys.argv[3]
+ exp_test_file_name = sys.argv[4]
+ act_test_file_name = sys.argv[5]
+
+ try:
+ template_file = open (template_file_name, 'rt')
+ exp_stdout_file = open (exp_stdout_file_name, 'rt')
+ act_stdout_file = open (act_stdout_file_name, 'rt')
+ exp_test_file = open (exp_test_file_name, 'rt')
+ act_test_file = open (act_test_file_name, 'rt')
+ except FileNotFoundError:
+ print ('One or more files could not be found.')
+ usage();
+ sys.exit(4)
+ except:
+ print ('Something went wrong trying to open the input files.')
+ usage();
+ sys.exit(5)
+ else:
+ message = '\nInput files:\n {},\n {},\n {},\n'
+ message += ' {}, and\n {}\nopened successfully.\n'
+ if not quiet:
+ print (message.format (template_file_name, exp_stdout_file_name,
+ act_stdout_file_name, exp_test_file_name, act_test_file_name))
+
+ # Check it all:
+ if not quiet: print ("\nChecking test C file: ", end="")
+ line_by_line.check_file ( exp_test_file, exp_test_file_name,
+ act_test_file, act_test_file_name,
+ loud, quiet, ultra_quiet )
+ if not quiet: print ("Checking stdout and stderr: ", end="")
+ line_by_line.check_file ( exp_stdout_file, exp_stdout_file_name,
+ act_stdout_file, act_stdout_file_name,
+ loud, quiet, ultra_quiet )
+
+ # Ran to completion normally, so pass:
+ if not ultra_quiet: print ("Regression test passed.")
+ sys.exit(0)
+
+if __name__ == "__main__": main()
diff --git a/tf_fuzz/regression/000017_read_sst_check_single_asset_multiple_times/exp_stdout_stderr b/tf_fuzz/regression/000017_read_sst_check_single_asset_multiple_times/exp_stdout_stderr
new file mode 100644
index 0000000..990480d
--- /dev/null
+++ b/tf_fuzz/regression/000017_read_sst_check_single_asset_multiple_times/exp_stdout_stderr
@@ -0,0 +1,68 @@
+Trusted Firmware Fuzzer (TF-Fuzz) starting...
+
+Info: random seed was not specified.
+
+Using seed value of \d+ \(0x[a-f\d]+\).
+Purpose line: to read the value of a single asset multiple times
+ASSET_IDENTIFIER: "just_checking"
+Asset identifier list: "data"
+Create from random data
+Set SST command: ";"
+Appended to end of call sequence: SST-set call.
+Set command: ";"
+Command with no expect: ";"
+ASSET_IDENTIFIER: "just_checking"
+Asset identifier list: "check"
+LITERAL string: "Not this"
+Read check against literal: "Not this"
+SST-read arguments: expect"
+Read SST command: "expect"
+Appended to end of call sequence: SST-get call.
+Read command: "expect"
+Expect fail clause: "fail"
+Command with expect: ";"
+ASSET_IDENTIFIER: "just_checking"
+Asset identifier list: "check"
+LITERAL string: "Not this either"
+Read check against literal: "Not this either"
+SST-read arguments: expect"
+Read SST command: "expect"
+Appended to end of call sequence: SST-get call.
+Read command: "expect"
+Expect fail clause: "fail"
+Command with expect: ";"
+ASSET_IDENTIFIER: "just_checking"
+Asset identifier list: "check"
+LITERAL string: "No dice on this either"
+Read check against literal: "No dice on this either"
+SST-read arguments: expect"
+Read SST command: "expect"
+Appended to end of call sequence: SST-get call.
+Read command: "expect"
+Expect fail clause: "fail"
+Command with expect: ";"
+ASSET_IDENTIFIER: "just_checking"
+Asset identifier list: "print"
+Read log to test log: "print"
+SST-read arguments: ;"
+Read SST command: ";"
+Appended to end of call sequence: SST-get call.
+Read command: ";"
+Command with no expect: ";"
+Lines: Line number 8.
+Lines: Line number 8.
+Lines: Line number 8.
+Lines: Line number 8.
+Lines: Line number 8.
+Lines: Line number 8.
+Call sequence generated.
+Simulating call sequence...
+Call sequence:
+ SST-set call for asset just_checking
+ SST-get call for asset just_checking
+ SST-get call for asset just_checking
+ SST-get call for asset just_checking
+ SST-get call for asset just_checking
+Writing test file, ./test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tf_fuzz/regression/000017_read_sst_check_single_asset_multiple_times/exp_test.c b/tf_fuzz/regression/000017_read_sst_check_single_asset_multiple_times/exp_test.c
new file mode 100644
index 0000000..aa333ab
--- /dev/null
+++ b/tf_fuzz/regression/000017_read_sst_check_single_asset_multiple_times/exp_test.c
@@ -0,0 +1,109 @@
+/*
+ * Test purpose:
+ * to read the value of a single asset multiple times
+ *
+ */
+
+#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 "tfm_memory_utils.h"
+#include "psa/crypto.h"
+#include "psa/crypto_sizes.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;
+ /* Variables (etc.) to initialize and check PSA assets: */
+ static uint8_t just_checking_set_data\[\] = "@@001@10@@[a-z\ ]*[\.\?\!]";
+ static uint32_t just_checking_set_length = \d+;
+ static uint8_t just_checking_exp_data[] = "Not this";
+ static uint8_t just_checking_act_data\[2048\] = "[A-Z][a-z ]*[\.\?\!]";
+ static size_t just_checking_act_length = \d+;
+ static uint8_t just_checking_exp_data_1[] = "Not this either";
+ static uint8_t just_checking_exp_data_2[] = "No dice on this either";
+ (void)sst_status;
+ /* "void" to prevent unused-variable warning, since the variable may not
+ * be used in this particular test case.
+ */
+
+ crypto_status = psa_crypto_init();
+ if (crypto_status != PSA_SUCCESS) {
+ TEST_FAIL("Could not initialize Crypto.");
+ return;
+ }
+
+ TEST_LOG("Test to read the value of a single asset multiple times");
+
+
+ /* PSA calls to test: */
+ /\* Creating SST asset "just_checking," with data "@@001@10@@...". \*/
+ sst_status = psa_ps_set\(@@@001@@@, just_checking_set_length, just_checking_set_data,
+ PSA_STORAGE_FLAG_[A-Z_]+\);
+ if (sst_status != PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+ return;
+ }
+ sst_status = psa_ps_get\(@@@001@@@, 0, \d+, just_checking_act_data,
+ &just_checking_act_length);
+ if (sst_status == PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_get() expected not PSA_SUCCESS.");
+ return;
+ }
+ /* Check that the data is correct */
+ if \(tfm_memcmp\(just_checking_act_data, just_checking_exp_data,
+ just_checking_act_length\) != 0\) {
+ TEST_FAIL("Read data should be equal to result data");
+ return;
+ }
+ sst_status = psa_ps_get\(@@@001@@@, 0, \d+, just_checking_act_data,
+ &just_checking_act_length);
+ if (sst_status == PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_get() expected not PSA_SUCCESS.");
+ return;
+ }
+ /* Check that the data is correct */
+ if \(tfm_memcmp\(just_checking_act_data, just_checking_exp_data_1,
+ just_checking_act_length\) != 0\) {
+ TEST_FAIL("Read data should be equal to result data");
+ return;
+ }
+ sst_status = psa_ps_get\(@@@001@@@, 0, \d+, just_checking_act_data,
+ &just_checking_act_length);
+ if (sst_status == PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_get() expected not PSA_SUCCESS.");
+ return;
+ }
+ /* Check that the data is correct */
+ if \(tfm_memcmp\(just_checking_act_data, just_checking_exp_data_2,
+ just_checking_act_length\) != 0\) {
+ TEST_FAIL("Read data should be equal to result data");
+ return;
+ }
+ sst_status = psa_ps_get\(@@@001@@@, 0, \d+, just_checking_act_data,
+ &just_checking_act_length);
+ if (sst_status != PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_get() expected PSA_SUCCESS.");
+ return;
+ }
+ TEST_LOG\(\"just_checking_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/tf_fuzz/regression/000017_read_sst_check_single_asset_multiple_times/template b/tf_fuzz/regression/000017_read_sst_check_single_asset_multiple_times/template
new file mode 100644
index 0000000..9f10122
--- /dev/null
+++ b/tf_fuzz/regression/000017_read_sst_check_single_asset_multiple_times/template
@@ -0,0 +1,7 @@
+purpose to read the value of a single asset multiple times;
+set sst name just_checking data *;
+// TF-Fuzz needs enhancements to correctly predict the "expect" values below:
+read sst name just_checking check "Not this" expect fail;
+read sst name just_checking check "Not this either" expect fail;
+read sst name just_checking check "No dice on this either" expect fail;
+read sst name just_checking print;
diff --git a/tf_fuzz/regression/000018_000016_and_000017/check.py b/tf_fuzz/regression/000018_000016_and_000017/check.py
new file mode 100644
index 0000000..1bc5cbe
--- /dev/null
+++ b/tf_fuzz/regression/000018_000016_and_000017/check.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+'''
+ Please read .../tf_fuzz/regression/README to understand this code.
+
+ Please also read the comments in .../tf_fuzz/regression/regress_lib/line_by_line.py.
+'''
+
+import sys, os, re, string, pdb
+sys.path.append ("../regress_lib")
+import line_by_line
+
+
+# Describe script usage:
+def usage():
+ print ('''
+ Command-line parameters:
+ 1. The test-template file, nominally named "template",
+ 2. The expected combined stdout/stderr output, nominally named "exp_stdout_stderr",
+ 3. The actual/generated combined stdout/stderr output, nominally named "stdout_stderr",
+ 4. The expected .c test file, nominally named "exp_test.c", and
+ 5. The actual, generated .c test file, nominally named "test.c".
+
+ Optionally, *before* these five arguments, you may add switches thus:
+ "--v" for verbose mode, to view line-by-line comparisons actual vs. expected,
+ "--q" to only print error messages and a successful-completion message,
+ "--qq" same as --q but not even printing out the completion message, and
+ "--s 12345" to run TF-Fuzz with seed value 12345 (or whatever).
+ ''')
+
+
+def main():
+ # See if we're supposed to be quiet:
+ loud = quiet = ultra_quiet = False
+ seed = ""
+ while sys.argv[1][0] == "-":
+ if sys.argv[1] == "--v":
+ loud = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--q":
+ quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--qq":
+ quiet = ultra_quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--s":
+ sys.argv.pop(1)
+ seed = sys.argv[1]
+ sys.argv.pop(1)
+ if not seed.isnumeric():
+ print ('The --s seed argument was not a number.')
+ usage()
+ sys.exit(1)
+
+ # Run TF-Fuzz:
+ if not quiet: print ("Running TF-Fuzz... ")
+ os.system ('rm -f stdout_stderr test.c')
+ command = '../../tfz -v ./' + sys.argv[1] + ' ./' + sys.argv[5]
+ command += ' ' + seed + ' >' + sys.argv[3] + ' 2>&1'
+ if loud:
+ print (command)
+ if os.system (command) == 0:
+ if not quiet: print ("TF-Fuzz run complete.")
+ else:
+ print ('Could not run TF-Fuzz; please see stdout_stderr file.')
+ sys.exit(2)
+
+ # Attempt to open files indicated on command line:
+ if len(sys.argv) != 6:
+ message = '{} requires 5 command-line arguments. Exiting.'
+ print (message.format(sys.argv[0]), file=sys.stderr)
+ usage()
+ sys.exit(3)
+ template_file_name = sys.argv[1]
+ exp_stdout_file_name = sys.argv[2]
+ act_stdout_file_name = sys.argv[3]
+ exp_test_file_name = sys.argv[4]
+ act_test_file_name = sys.argv[5]
+
+ try:
+ template_file = open (template_file_name, 'rt')
+ exp_stdout_file = open (exp_stdout_file_name, 'rt')
+ act_stdout_file = open (act_stdout_file_name, 'rt')
+ exp_test_file = open (exp_test_file_name, 'rt')
+ act_test_file = open (act_test_file_name, 'rt')
+ except FileNotFoundError:
+ print ('One or more files could not be found.')
+ usage();
+ sys.exit(4)
+ except:
+ print ('Something went wrong trying to open the input files.')
+ usage();
+ sys.exit(5)
+ else:
+ message = '\nInput files:\n {},\n {},\n {},\n'
+ message += ' {}, and\n {}\nopened successfully.\n'
+ if not quiet:
+ print (message.format (template_file_name, exp_stdout_file_name,
+ act_stdout_file_name, exp_test_file_name, act_test_file_name))
+
+ # Check it all:
+ if not quiet: print ("\nChecking test C file: ", end="")
+ line_by_line.check_file ( exp_test_file, exp_test_file_name,
+ act_test_file, act_test_file_name,
+ loud, quiet, ultra_quiet )
+ if not quiet: print ("Checking stdout and stderr: ", end="")
+ line_by_line.check_file ( exp_stdout_file, exp_stdout_file_name,
+ act_stdout_file, act_stdout_file_name,
+ loud, quiet, ultra_quiet )
+
+ # Ran to completion normally, so pass:
+ if not ultra_quiet: print ("Regression test passed.")
+ sys.exit(0)
+
+if __name__ == "__main__": main()
diff --git a/tf_fuzz/regression/000018_000016_and_000017/exp_stdout_stderr b/tf_fuzz/regression/000018_000016_and_000017/exp_stdout_stderr
new file mode 100644
index 0000000..e9fad8a
--- /dev/null
+++ b/tf_fuzz/regression/000018_000016_and_000017/exp_stdout_stderr
@@ -0,0 +1,121 @@
+Trusted Firmware Fuzzer (TF-Fuzz) starting...
+
+Info: random seed was not specified.
+
+Using seed value of \d+ \(0x[a-f\d]+\).
+Purpose line: to both read the value of a single asset multiple times and assign a sequence of values to a single asset
+ASSET_IDENTIFIER: "indecisive"
+Asset identifier list: "data"
+LITERAL string: "First value"
+Create from literal data: ""First value""
+SST no storage flag: none"
+SST creation flag
+;"
+SST creation flags
+;"
+Set SST command: ";"
+Appended to end of call sequence: SST-set call.
+Set command: ";"
+Command with no expect: ";"
+ASSET_IDENTIFIER: "indecisive"
+Asset identifier list: "check"
+LITERAL string: "Not this"
+Read check against literal: "Not this"
+SST-read arguments: expect"
+Read SST command: "expect"
+Appended to end of call sequence: SST-get call.
+Read command: "expect"
+Expect fail clause: "fail"
+Command with expect: ";"
+ASSET_IDENTIFIER: "indecisive"
+Asset identifier list: "data"
+LITERAL string: "Second value"
+Create from literal data: ""Second value""
+Set SST command: ";"
+Appended to end of call sequence: SST-set call.
+Set command: ";"
+Command with no expect: ";"
+ASSET_IDENTIFIER: "indecisive"
+Asset identifier list: "check"
+LITERAL string: "Not this either"
+Read check against literal: "Not this either"
+SST-read arguments: expect"
+Read SST command: "expect"
+Appended to end of call sequence: SST-get call.
+Read command: "expect"
+Expect fail clause: "fail"
+Command with expect: ";"
+ASSET_IDENTIFIER: "indecisive"
+Asset identifier list: "data"
+Create from random data
+Set SST command: ";"
+Appended to end of call sequence: SST-set call.
+Set command: ";"
+Command with no expect: ";"
+ASSET_IDENTIFIER: "indecisive"
+Asset identifier list: "data"
+LITERAL string: "Fourth value"
+Create from literal data: ""Fourth value""
+Set SST command: ";"
+Appended to end of call sequence: SST-set call.
+Set command: ";"
+Command with no expect: ";"
+ASSET_IDENTIFIER: "indecisive"
+Asset identifier list: "check"
+LITERAL string: "No dice on this either"
+Read check against literal: "No dice on this either"
+SST-read arguments: expect"
+Read SST command: "expect"
+Appended to end of call sequence: SST-get call.
+Read command: "expect"
+Expect fail clause: "fail"
+Command with expect: ";"
+ASSET_IDENTIFIER: "indecisive"
+Asset identifier list: "data"
+Create from random data
+Set SST command: ";"
+Appended to end of call sequence: SST-set call.
+Set command: ";"
+Command with no expect: ";"
+ASSET_IDENTIFIER: "indecisive"
+Asset identifier list: "data"
+Create from random data
+Set SST command: ";"
+Appended to end of call sequence: SST-set call.
+Set command: ";"
+Command with no expect: ";"
+ASSET_IDENTIFIER: "indecisive"
+Asset identifier list: "print"
+Read log to test log: "print"
+SST-read arguments: ;"
+Read SST command: ";"
+Appended to end of call sequence: SST-get call.
+Read command: ";"
+Command with no expect: ";"
+Lines: Line number 12.
+Lines: Line number 12.
+Lines: Line number 12.
+Lines: Line number 12.
+Lines: Line number 12.
+Lines: Line number 12.
+Lines: Line number 12.
+Lines: Line number 12.
+Lines: Line number 12.
+Lines: Line number 12.
+Lines: Line number 12.
+Call sequence generated.
+Simulating call sequence...
+Call sequence:
+ SST-set call for asset indecisive
+ SST-get call for asset indecisive
+ SST-set call for asset indecisive
+ SST-get call for asset indecisive
+ SST-set call for asset indecisive
+ SST-set call for asset indecisive
+ SST-get call for asset indecisive
+ SST-set call for asset indecisive
+ SST-set call for asset indecisive
+ SST-get call for asset indecisive
+Writing test file, ./test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tf_fuzz/regression/000018_000016_and_000017/exp_test.c b/tf_fuzz/regression/000018_000016_and_000017/exp_test.c
new file mode 100644
index 0000000..ca1ba06
--- /dev/null
+++ b/tf_fuzz/regression/000018_000016_and_000017/exp_test.c
@@ -0,0 +1,154 @@
+/*
+ * Test purpose:
+ * to both read the value of a single asset multiple times and assign a sequence of values to a single 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 "tfm_memory_utils.h"
+#include "psa/crypto.h"
+#include "psa/crypto_sizes.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;
+ /* Variables (etc.) to initialize and check PSA assets: */
+ static uint8_t indecisive_set_data[] = "First value";
+ static uint32_t indecisive_set_length = 11;
+ static uint8_t indecisive_exp_data[] = "Not this";
+ static uint8_t indecisive_act_data\[2048\] = "[A-Z][a-z ]*[\.\?\!]";
+ static size_t indecisive_act_length = \d+;
+ static uint8_t indecisive_set_data_1[] = "Second value";
+ static uint32_t indecisive_set_length_1 = 12;
+ static uint8_t indecisive_exp_data_1[] = "Not this either";
+ static uint8_t indecisive_set_data_2\[\] = "@@001@10@@[a-z\ ]*[\.\?\!]";
+ static uint32_t indecisive_set_length_2 = \d+;
+ static uint8_t indecisive_set_data_3[] = "Fourth value";
+ static uint32_t indecisive_set_length_3 = 12;
+ static uint8_t indecisive_exp_data_2[] = "No dice on this either";
+ static uint8_t indecisive_set_data_4\[\] = "@@002@10@@[a-z\ ]*[\.\?\!]";
+ static uint32_t indecisive_set_length_4 = \d+;
+ static uint8_t indecisive_set_data_5\[\] = "@@003@10@@[a-z\ ]*[\.\?\!]";
+ static uint32_t indecisive_set_length_5 = \d+;
+ (void)sst_status;
+ /* "void" to prevent unused-variable warning, since the variable may not
+ * be used in this particular test case.
+ */
+
+ crypto_status = psa_crypto_init();
+ if (crypto_status != PSA_SUCCESS) {
+ TEST_FAIL("Could not initialize Crypto.");
+ return;
+ }
+
+ TEST_LOG("Test to both read the value of a single asset multiple times and assign a sequence of values to a single asset");
+
+
+ /* PSA calls to test: */
+ /* Creating SST asset "indecisive," with data "First valu...". */
+ sst_status = psa_ps_set\(@@@001@@@, indecisive_set_length, indecisive_set_data,
+ PSA_STORAGE_FLAG_NONE);
+ if (sst_status != PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+ return;
+ }
+ sst_status = psa_ps_get\(@@@001@@@, 0, 11, indecisive_act_data,
+ &indecisive_act_length);
+ if (sst_status == PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_get() expected not PSA_SUCCESS.");
+ return;
+ }
+ /* Check that the data is correct */
+ if (tfm_memcmp(indecisive_act_data, indecisive_exp_data,
+ indecisive_act_length\) != 0\) {
+ TEST_FAIL("Read data should be equal to result data");
+ return;
+ }
+ /* Resetting SST asset "indecisive," with data "Second val...". */
+ sst_status = psa_ps_set\(@@@001@@@, indecisive_set_length_1, indecisive_set_data_1,
+ PSA_STORAGE_FLAG_NONE);
+ if (sst_status != PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+ return;
+ }
+ sst_status = psa_ps_get\(@@@001@@@, 0, 12, indecisive_act_data,
+ &indecisive_act_length);
+ if (sst_status == PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_get() expected not PSA_SUCCESS.");
+ return;
+ }
+ /* Check that the data is correct */
+ if (tfm_memcmp(indecisive_act_data, indecisive_exp_data_1,
+ indecisive_act_length) != 0) {
+ TEST_FAIL("Read data should be equal to result data");
+ return;
+ }
+ /\* Resetting SST asset "indecisive," with data "@@001@10@@...". \*/
+ sst_status = psa_ps_set\(@@@001@@@, indecisive_set_length_2, indecisive_set_data_2,
+ PSA_STORAGE_FLAG_NONE);
+ if (sst_status != PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+ return;
+ }
+ /* Resetting SST asset "indecisive," with data "Fourth val...". */
+ sst_status = psa_ps_set\(@@@001@@@, indecisive_set_length_3, indecisive_set_data_3,
+ PSA_STORAGE_FLAG_NONE);
+ if (sst_status != PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+ return;
+ }
+ sst_status = psa_ps_get\(@@@001@@@, 0, 12, indecisive_act_data,
+ &indecisive_act_length);
+ if (sst_status == PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_get() expected not PSA_SUCCESS.");
+ return;
+ }
+ /* Check that the data is correct */
+ if (tfm_memcmp(indecisive_act_data, indecisive_exp_data_2,
+ indecisive_act_length) != 0) {
+ TEST_FAIL("Read data should be equal to result data");
+ return;
+ }
+ /\* Resetting SST asset "indecisive," with data "@@002@10@@...". \*/
+ sst_status = psa_ps_set\(@@@001@@@, indecisive_set_length_4, indecisive_set_data_4,
+ PSA_STORAGE_FLAG_NONE);
+ if (sst_status != PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+ return;
+ }
+ /\* Resetting SST asset "indecisive," with data "@@003@10@@...". \*/
+ sst_status = psa_ps_set\(@@@001@@@, indecisive_set_length_5, indecisive_set_data_5,
+ PSA_STORAGE_FLAG_NONE);
+ if (sst_status != PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+ return;
+ }
+ sst_status = psa_ps_get\(@@@001@@@, 0, \d+, indecisive_act_data,
+ &indecisive_act_length);
+ if (sst_status != PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_get() expected PSA_SUCCESS.");
+ return;
+ }
+ TEST_LOG\(\"indecisive_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/tf_fuzz/regression/000018_000016_and_000017/template b/tf_fuzz/regression/000018_000016_and_000017/template
new file mode 100644
index 0000000..662a252
--- /dev/null
+++ b/tf_fuzz/regression/000018_000016_and_000017/template
@@ -0,0 +1,11 @@
+purpose to both read the value of a single asset multiple times and assign a sequence of values to a single asset;
+set sst name indecisive data "First value" flag none;
+read sst name indecisive check "Not this" expect fail;
+set sst name indecisive data "Second value";
+read sst name indecisive check "Not this either" expect fail;
+set sst name indecisive data *;
+set sst name indecisive data "Fourth value";
+read sst name indecisive check "No dice on this either" expect fail;
+set sst name indecisive data *;
+set sst name indecisive data *;
+read sst name indecisive print;
diff --git a/tf_fuzz/regression/000019_read_asset_to_variable_set_other_asset/check.py b/tf_fuzz/regression/000019_read_asset_to_variable_set_other_asset/check.py
new file mode 100644
index 0000000..1bc5cbe
--- /dev/null
+++ b/tf_fuzz/regression/000019_read_asset_to_variable_set_other_asset/check.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+'''
+ Please read .../tf_fuzz/regression/README to understand this code.
+
+ Please also read the comments in .../tf_fuzz/regression/regress_lib/line_by_line.py.
+'''
+
+import sys, os, re, string, pdb
+sys.path.append ("../regress_lib")
+import line_by_line
+
+
+# Describe script usage:
+def usage():
+ print ('''
+ Command-line parameters:
+ 1. The test-template file, nominally named "template",
+ 2. The expected combined stdout/stderr output, nominally named "exp_stdout_stderr",
+ 3. The actual/generated combined stdout/stderr output, nominally named "stdout_stderr",
+ 4. The expected .c test file, nominally named "exp_test.c", and
+ 5. The actual, generated .c test file, nominally named "test.c".
+
+ Optionally, *before* these five arguments, you may add switches thus:
+ "--v" for verbose mode, to view line-by-line comparisons actual vs. expected,
+ "--q" to only print error messages and a successful-completion message,
+ "--qq" same as --q but not even printing out the completion message, and
+ "--s 12345" to run TF-Fuzz with seed value 12345 (or whatever).
+ ''')
+
+
+def main():
+ # See if we're supposed to be quiet:
+ loud = quiet = ultra_quiet = False
+ seed = ""
+ while sys.argv[1][0] == "-":
+ if sys.argv[1] == "--v":
+ loud = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--q":
+ quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--qq":
+ quiet = ultra_quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--s":
+ sys.argv.pop(1)
+ seed = sys.argv[1]
+ sys.argv.pop(1)
+ if not seed.isnumeric():
+ print ('The --s seed argument was not a number.')
+ usage()
+ sys.exit(1)
+
+ # Run TF-Fuzz:
+ if not quiet: print ("Running TF-Fuzz... ")
+ os.system ('rm -f stdout_stderr test.c')
+ command = '../../tfz -v ./' + sys.argv[1] + ' ./' + sys.argv[5]
+ command += ' ' + seed + ' >' + sys.argv[3] + ' 2>&1'
+ if loud:
+ print (command)
+ if os.system (command) == 0:
+ if not quiet: print ("TF-Fuzz run complete.")
+ else:
+ print ('Could not run TF-Fuzz; please see stdout_stderr file.')
+ sys.exit(2)
+
+ # Attempt to open files indicated on command line:
+ if len(sys.argv) != 6:
+ message = '{} requires 5 command-line arguments. Exiting.'
+ print (message.format(sys.argv[0]), file=sys.stderr)
+ usage()
+ sys.exit(3)
+ template_file_name = sys.argv[1]
+ exp_stdout_file_name = sys.argv[2]
+ act_stdout_file_name = sys.argv[3]
+ exp_test_file_name = sys.argv[4]
+ act_test_file_name = sys.argv[5]
+
+ try:
+ template_file = open (template_file_name, 'rt')
+ exp_stdout_file = open (exp_stdout_file_name, 'rt')
+ act_stdout_file = open (act_stdout_file_name, 'rt')
+ exp_test_file = open (exp_test_file_name, 'rt')
+ act_test_file = open (act_test_file_name, 'rt')
+ except FileNotFoundError:
+ print ('One or more files could not be found.')
+ usage();
+ sys.exit(4)
+ except:
+ print ('Something went wrong trying to open the input files.')
+ usage();
+ sys.exit(5)
+ else:
+ message = '\nInput files:\n {},\n {},\n {},\n'
+ message += ' {}, and\n {}\nopened successfully.\n'
+ if not quiet:
+ print (message.format (template_file_name, exp_stdout_file_name,
+ act_stdout_file_name, exp_test_file_name, act_test_file_name))
+
+ # Check it all:
+ if not quiet: print ("\nChecking test C file: ", end="")
+ line_by_line.check_file ( exp_test_file, exp_test_file_name,
+ act_test_file, act_test_file_name,
+ loud, quiet, ultra_quiet )
+ if not quiet: print ("Checking stdout and stderr: ", end="")
+ line_by_line.check_file ( exp_stdout_file, exp_stdout_file_name,
+ act_stdout_file, act_stdout_file_name,
+ loud, quiet, ultra_quiet )
+
+ # Ran to completion normally, so pass:
+ if not ultra_quiet: print ("Regression test passed.")
+ sys.exit(0)
+
+if __name__ == "__main__": main()
diff --git a/tf_fuzz/regression/000019_read_asset_to_variable_set_other_asset/exp_stdout_stderr b/tf_fuzz/regression/000019_read_asset_to_variable_set_other_asset/exp_stdout_stderr
new file mode 100644
index 0000000..ca4b2ed
--- /dev/null
+++ b/tf_fuzz/regression/000019_read_asset_to_variable_set_other_asset/exp_stdout_stderr
@@ -0,0 +1,76 @@
+Trusted Firmware Fuzzer (TF-Fuzz) starting...
+
+Info: random seed was not specified.
+
+Using seed value of \d+ \(0x[a-f\d]+\).
+Purpose line: to read an asset into a named variable the set another asset from that variable
+ASSET_IDENTIFIER: "source"
+Asset identifier list: ";"
+SST-create from random data (no 'data *')
+Set SST command: ";"
+Appended to end of call sequence: SST-set call.
+Set command: ";"
+Command with no expect: ";"
+ASSET_IDENTIFIER: "source"
+Asset identifier list: "var"
+IDENTIFIER: "transfer"
+Read dump to variable: "transfer"
+SST-read arguments: ;"
+Read SST command: ";"
+Appended to end of call sequence: SST-get call.
+Read command: ";"
+Command with no expect: ";"
+ASSET_IDENTIFIER: "intermediate"
+Asset identifier list: "var"
+IDENTIFIER: "transfer"
+SST-set set from variable: "transfer"
+Set SST command: ";"
+Appended to end of call sequence: SST-set call.
+Set command: ";"
+Command with no expect: ";"
+ASSET_IDENTIFIER: "intermediate"
+Asset identifier list: "var"
+IDENTIFIER: "transfer"
+Read dump to variable: "transfer"
+SST-read arguments: ;"
+Read SST command: ";"
+Appended to end of call sequence: SST-get call.
+Read command: ";"
+Command with no expect: ";"
+ASSET_IDENTIFIER: "destination"
+Asset identifier list: "var"
+IDENTIFIER: "transfer"
+SST-set set from variable: "transfer"
+Set SST command: ";"
+Appended to end of call sequence: SST-set call.
+Set command: ";"
+Command with no expect: ";"
+ASSET_IDENTIFIER: "destination"
+Asset identifier list: "check"
+IDENTIFIER: "transfer"
+Read-arguments variable name: "transfer"
+Read check against variable: "transfer"
+SST-read arguments: ;"
+Read SST command: ";"
+Appended to end of call sequence: SST-get call.
+Read command: ";"
+Command with no expect: ";"
+Lines: Line number 8.
+Lines: Line number 8.
+Lines: Line number 8.
+Lines: Line number 8.
+Lines: Line number 8.
+Lines: Line number 8.
+Lines: Line number 8.
+Call sequence generated.
+Simulating call sequence...
+Call sequence:
+ SST-set call for asset source
+ SST-get call for asset source
+ SST-set call for asset intermediate
+ SST-get call for asset intermediate
+ SST-set call for asset destination
+ SST-get call for asset destination
+Writing test file, ./test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tf_fuzz/regression/000019_read_asset_to_variable_set_other_asset/exp_test.c b/tf_fuzz/regression/000019_read_asset_to_variable_set_other_asset/exp_test.c
new file mode 100644
index 0000000..6131299
--- /dev/null
+++ b/tf_fuzz/regression/000019_read_asset_to_variable_set_other_asset/exp_test.c
@@ -0,0 +1,127 @@
+/*
+ * Test purpose:
+ * to read an asset into a named variable the set another asset from that variable
+ *
+ */
+
+#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 "tfm_memory_utils.h"
+#include "psa/crypto.h"
+#include "psa/crypto_sizes.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;
+ /* Variables (etc.) to initialize and check PSA assets: */
+ static uint8_t source_set_data\[\] = "@@001@10@@[a-z\ ]*[\.\?\!]";
+ static uint32_t source_set_length = @@@004@@@;
+ static uint8_t source_exp_data\[\] = "@@001@10@@[a-z\ ]*[\.\?\!]";
+ static uint8_t transfer_data\[2048\] = "[A-Z][a-z ]*[\.\?\!]";
+ static size_t transfer_length = \d+;
+ static uint8_t intermediate_exp_data\[\] = "@@002@10@@[a-z\ ]*[\.\?\!]";
+ static uint8_t destination_act_data\[2048\] = "[A-Z][a-z ]*[\.\?\!]";
+ static size_t destination_act_length = \d+;
+ (void)sst_status;
+ /* "void" to prevent unused-variable warning, since the variable may not
+ * be used in this particular test case.
+ */
+
+ crypto_status = psa_crypto_init();
+ if (crypto_status != PSA_SUCCESS) {
+ TEST_FAIL("Could not initialize Crypto.");
+ return;
+ }
+
+ TEST_LOG("Test to read an asset into a named variable the set another asset from that variable");
+
+
+ /* PSA calls to test: */
+ /\* Creating SST asset "source," with data "@@001@10@@...". \*/
+ sst_status = psa_ps_set\(@@@001@@@, source_set_length, source_set_data,
+ PSA_STORAGE_FLAG_[A-Z_]+\);
+ if (sst_status != PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+ return;
+ }
+ sst_status = psa_ps_get\(@@@001@@@, 0, @@@004@@@, transfer_data,
+ &transfer_length);
+ if (sst_status != PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_get() expected PSA_SUCCESS.");
+ return;
+ }
+ /* Check that the data is correct */
+ if (tfm_memcmp(transfer_data, source_exp_data,
+ transfer_length) != 0) {
+ TEST_FAIL("Read data should be equal to result data");
+ return;
+ }
+ /\* Creating SST asset "intermediate," with data "@@002@10@@...". \*/
+ sst_status = psa_ps_set\(@@@002@@@, transfer_length, transfer_data,
+ PSA_STORAGE_FLAG_[A-Z_]+\);
+ if (sst_status != PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+ return;
+ }
+ sst_status = psa_ps_get\(@@@002@@@, 0, \d+, transfer_data,
+ &transfer_length);
+ if (sst_status != PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_get() expected PSA_SUCCESS.");
+ return;
+ }
+ /* Check that the data is correct */
+ if (tfm_memcmp(transfer_data, intermediate_exp_data,
+ transfer_length) != 0) {
+ TEST_FAIL("Read data should be equal to result data");
+ return;
+ }
+ /\* Creating SST asset "destination," with data "[A-Z][a-z ]*...". \*/
+ sst_status = psa_ps_set\(@@@003@@@, transfer_length, transfer_data,
+ PSA_STORAGE_FLAG_[A-Z_]+\);
+ if (sst_status != PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+ return;
+ }
+ sst_status = psa_ps_get\(@@@003@@@, 0, \d+, destination_act_data,
+ &destination_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(destination_act_data, transfer_data,
+ destination_act_length) != 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;
+ }
+ 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;
+ }
+
+ /* Test completed */
+ ret->val = TEST_PASSED;
+}
diff --git a/tf_fuzz/regression/000019_read_asset_to_variable_set_other_asset/template b/tf_fuzz/regression/000019_read_asset_to_variable_set_other_asset/template
new file mode 100644
index 0000000..0111ba2
--- /dev/null
+++ b/tf_fuzz/regression/000019_read_asset_to_variable_set_other_asset/template
@@ -0,0 +1,7 @@
+purpose to read an asset into a named variable the set another asset from that variable;
+set sst name source; // shorthand for random data
+read sst name source var transfer;
+set sst name intermediate var transfer;
+read sst name intermediate var transfer;
+set sst name destination var transfer;
+read sst name destination check transfer;
diff --git a/tf_fuzz/regression/000020_no_purpose/check.py b/tf_fuzz/regression/000020_no_purpose/check.py
new file mode 100644
index 0000000..2027be8
--- /dev/null
+++ b/tf_fuzz/regression/000020_no_purpose/check.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+'''
+ Please read .../tf_fuzz/regression/README to understand this code.
+
+ Please also read the comments in .../tf_fuzz/regression/regress_lib/line_by_line.py.
+'''
+
+import sys, os, re, string, pdb
+sys.path.append ("../regress_lib")
+import line_by_line
+
+
+# Describe script usage:
+def usage():
+ print ('''
+ Command-line parameters:
+ 1. The test-template file, nominally named "template",
+ 2. The expected combined stdout/stderr output, nominally named "exp_stdout_stderr",
+ 3. The actual/generated combined stdout/stderr output, nominally named "stdout_stderr",
+ 4. The expected .c test file, nominally named "exp_test.c", and
+ 5. The actual, generated .c test file, nominally named "test.c".
+
+ Optionally, *before* these five arguments, you may add switches thus:
+ "--v" for verbose mode, to view line-by-line comparisons actual vs. expected,
+ "--q" to only print error messages and a successful-completion message,
+ "--qq" same as --q but not even printing out the completion message, and
+ "--s 12345" to run TF-Fuzz with seed value 12345 (or whatever).
+ ''')
+
+
+def main():
+ # See if we're supposed to be quiet:
+ loud = quiet = ultra_quiet = False
+ seed = ""
+ while sys.argv[1][0] == "-":
+ if sys.argv[1] == "--v":
+ loud = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--q":
+ quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--qq":
+ quiet = ultra_quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--s":
+ sys.argv.pop(1)
+ seed = sys.argv[1]
+ sys.argv.pop(1)
+ if not seed.isnumeric():
+ print ('The --s seed argument was not a number.')
+ usage()
+ sys.exit(1)
+
+ # Run TF-Fuzz:
+ if not quiet: print ("Running TF-Fuzz... ")
+ os.system ('rm -f stdout_stderr test.c')
+ command = '../../tfz -v ./' + sys.argv[1] + ' ./' + sys.argv[5]
+ command += ' ' + seed + ' >' + sys.argv[3] + ' 2>&1'
+ if loud:
+ print (command)
+ if os.system (command) == 0:
+ if not quiet: print ("TF-Fuzz run complete.")
+ else:
+ print ('Could not run TF-Fuzz; please see stdout_stderr file.')
+ sys.exit(2)
+
+ # Attempt to open files indicated on command line:
+ if len(sys.argv) != 6:
+ message = '{} requires 5 command-line arguments. Exiting.'
+ print (message.format(sys.argv[0]), file=sys.stderr)
+ usage()
+ sys.exit(3)
+ template_file_name = sys.argv[1]
+ exp_stdout_file_name = sys.argv[2]
+ act_stdout_file_name = sys.argv[3]
+ exp_test_file_name = sys.argv[4]
+ act_test_file_name = sys.argv[5]
+
+ try:
+ template_file = open (template_file_name, 'rt')
+ exp_stdout_file = open (exp_stdout_file_name, 'rt')
+ act_stdout_file = open (act_stdout_file_name, 'rt')
+ exp_test_file = open (exp_test_file_name, 'rt')
+ act_test_file = open (act_test_file_name, 'rt')
+ except FileNotFoundError:
+ print ('One or more files could not be found.')
+ usage();
+ sys.exit(4)
+ except:
+ print ('Something went wrong trying to open the input files.')
+ usage();
+ sys.exit(5)
+ else:
+ message = '\nInput files:\n {},\n {},\n {},\n'
+ message += ' {}, and\n {}\nopened successfully.\n'
+ if not quiet:
+ print (message.format (template_file_name, exp_stdout_file_name,
+ act_stdout_file_name, exp_test_file_name, act_test_file_name))
+
+ # Check it all:
+ if not quiet: print ("\nChecking test C file: ", end="")
+ line_by_line.check_file ( exp_test_file, exp_test_file_name,
+ act_test_file, act_test_file_name,
+ loud, quiet, ultra_quiet )
+ if not quiet: print ("Checking stdout and stderr: ", end="")
+ line_by_line.check_file ( exp_stdout_file, exp_stdout_file_name,
+ act_stdout_file, act_stdout_file_name,
+ loud, quiet, ultra_quiet )
+
+ # Ran to completion normally, so pass:
+ if not ultra_quiet: print ("Regression test passed.")
+ sys.exit(0)
+
+if __name__ == "__main__": main()
diff --git a/tf_fuzz/regression/000020_no_purpose/exp_stdout_stderr b/tf_fuzz/regression/000020_no_purpose/exp_stdout_stderr
new file mode 100644
index 0000000..3a87ce6
--- /dev/null
+++ b/tf_fuzz/regression/000020_no_purpose/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]+\).
+ASSET_NUMBER: "104"
+SST-asset UID list: "data"
+LITERAL string: "Very simple test"
+Create from literal data: ""Very simple test""
+Set SST command: "expect"
+Appended to end of call sequence: SST-set call.
+Set command: "expect"
+Expect pass clause: "pass"
+Command with expect: "
+
+Error: Please begin your test with the "purpose" directive.
+ For example, "purpose to exercise crypto and SST..."
diff --git a/tf_fuzz/regression/000020_no_purpose/exp_test.c b/tf_fuzz/regression/000020_no_purpose/exp_test.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tf_fuzz/regression/000020_no_purpose/exp_test.c
diff --git a/tf_fuzz/regression/000020_no_purpose/template b/tf_fuzz/regression/000020_no_purpose/template
new file mode 100644
index 0000000..7b7fd92
--- /dev/null
+++ b/tf_fuzz/regression/000020_no_purpose/template
@@ -0,0 +1,2 @@
+// purpose to make sure it complains if you don't provide a purpose
+set sst uid 104 data "Very simple test" expect pass;
diff --git a/tf_fuzz/regression/000021_abbreviated_result_codes/check.py b/tf_fuzz/regression/000021_abbreviated_result_codes/check.py
new file mode 100644
index 0000000..2027be8
--- /dev/null
+++ b/tf_fuzz/regression/000021_abbreviated_result_codes/check.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+'''
+ Please read .../tf_fuzz/regression/README to understand this code.
+
+ Please also read the comments in .../tf_fuzz/regression/regress_lib/line_by_line.py.
+'''
+
+import sys, os, re, string, pdb
+sys.path.append ("../regress_lib")
+import line_by_line
+
+
+# Describe script usage:
+def usage():
+ print ('''
+ Command-line parameters:
+ 1. The test-template file, nominally named "template",
+ 2. The expected combined stdout/stderr output, nominally named "exp_stdout_stderr",
+ 3. The actual/generated combined stdout/stderr output, nominally named "stdout_stderr",
+ 4. The expected .c test file, nominally named "exp_test.c", and
+ 5. The actual, generated .c test file, nominally named "test.c".
+
+ Optionally, *before* these five arguments, you may add switches thus:
+ "--v" for verbose mode, to view line-by-line comparisons actual vs. expected,
+ "--q" to only print error messages and a successful-completion message,
+ "--qq" same as --q but not even printing out the completion message, and
+ "--s 12345" to run TF-Fuzz with seed value 12345 (or whatever).
+ ''')
+
+
+def main():
+ # See if we're supposed to be quiet:
+ loud = quiet = ultra_quiet = False
+ seed = ""
+ while sys.argv[1][0] == "-":
+ if sys.argv[1] == "--v":
+ loud = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--q":
+ quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--qq":
+ quiet = ultra_quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--s":
+ sys.argv.pop(1)
+ seed = sys.argv[1]
+ sys.argv.pop(1)
+ if not seed.isnumeric():
+ print ('The --s seed argument was not a number.')
+ usage()
+ sys.exit(1)
+
+ # Run TF-Fuzz:
+ if not quiet: print ("Running TF-Fuzz... ")
+ os.system ('rm -f stdout_stderr test.c')
+ command = '../../tfz -v ./' + sys.argv[1] + ' ./' + sys.argv[5]
+ command += ' ' + seed + ' >' + sys.argv[3] + ' 2>&1'
+ if loud:
+ print (command)
+ if os.system (command) == 0:
+ if not quiet: print ("TF-Fuzz run complete.")
+ else:
+ print ('Could not run TF-Fuzz; please see stdout_stderr file.')
+ sys.exit(2)
+
+ # Attempt to open files indicated on command line:
+ if len(sys.argv) != 6:
+ message = '{} requires 5 command-line arguments. Exiting.'
+ print (message.format(sys.argv[0]), file=sys.stderr)
+ usage()
+ sys.exit(3)
+ template_file_name = sys.argv[1]
+ exp_stdout_file_name = sys.argv[2]
+ act_stdout_file_name = sys.argv[3]
+ exp_test_file_name = sys.argv[4]
+ act_test_file_name = sys.argv[5]
+
+ try:
+ template_file = open (template_file_name, 'rt')
+ exp_stdout_file = open (exp_stdout_file_name, 'rt')
+ act_stdout_file = open (act_stdout_file_name, 'rt')
+ exp_test_file = open (exp_test_file_name, 'rt')
+ act_test_file = open (act_test_file_name, 'rt')
+ except FileNotFoundError:
+ print ('One or more files could not be found.')
+ usage();
+ sys.exit(4)
+ except:
+ print ('Something went wrong trying to open the input files.')
+ usage();
+ sys.exit(5)
+ else:
+ message = '\nInput files:\n {},\n {},\n {},\n'
+ message += ' {}, and\n {}\nopened successfully.\n'
+ if not quiet:
+ print (message.format (template_file_name, exp_stdout_file_name,
+ act_stdout_file_name, exp_test_file_name, act_test_file_name))
+
+ # Check it all:
+ if not quiet: print ("\nChecking test C file: ", end="")
+ line_by_line.check_file ( exp_test_file, exp_test_file_name,
+ act_test_file, act_test_file_name,
+ loud, quiet, ultra_quiet )
+ if not quiet: print ("Checking stdout and stderr: ", end="")
+ line_by_line.check_file ( exp_stdout_file, exp_stdout_file_name,
+ act_stdout_file, act_stdout_file_name,
+ loud, quiet, ultra_quiet )
+
+ # Ran to completion normally, so pass:
+ if not ultra_quiet: print ("Regression test passed.")
+ sys.exit(0)
+
+if __name__ == "__main__": main()
diff --git a/tf_fuzz/regression/000021_abbreviated_result_codes/exp_stdout_stderr b/tf_fuzz/regression/000021_abbreviated_result_codes/exp_stdout_stderr
new file mode 100644
index 0000000..c4af682
--- /dev/null
+++ b/tf_fuzz/regression/000021_abbreviated_result_codes/exp_stdout_stderr
@@ -0,0 +1,26 @@
+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"
+Asset identifier list: "chk"
+LITERAL string: "this won't work"
+Read check against literal: "this won't work"
+SST-read arguments: exp"
+Read SST command: "exp"
+Appended to end of call sequence: SST-get call.
+Read command: "exp"
+IDENTIFIER: "generic_error"
+Expect error clause: "generic_error"
+Command with expect: ";"
+Lines: Line number 3.
+Lines: Line number 3.
+Call sequence generated.
+Simulating call sequence...
+Call sequence:
+ SST-get call for asset napoleon
+Writing test file, ./test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tf_fuzz/regression/000021_abbreviated_result_codes/exp_test.c b/tf_fuzz/regression/000021_abbreviated_result_codes/exp_test.c
new file mode 100644
index 0000000..359dd8a
--- /dev/null
+++ b/tf_fuzz/regression/000021_abbreviated_result_codes/exp_test.c
@@ -0,0 +1,62 @@
+/*
+ * 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 "tfm_memory_utils.h"
+#include "psa/crypto.h"
+#include "psa/crypto_sizes.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;
+ /* 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\] = "[A-Z][a-z ]*[\.\?\!]";
+ static size_t napoleon_act_length = \d+;
+ (void)sst_status;
+ /* "void" to prevent unused-variable warning, since the variable may not
+ * be used in this particular test case.
+ */
+
+ 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");
+
+
+ /* PSA calls to test: */
+ sst_status = psa_ps_get\(\d+, 0, @@@001@@@, 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,
+ napoleon_act_length\) != 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/tf_fuzz/regression/000021_abbreviated_result_codes/template b/tf_fuzz/regression/000021_abbreviated_result_codes/template
new file mode 100644
index 0000000..67b05b3
--- /dev/null
+++ b/tf_fuzz/regression/000021_abbreviated_result_codes/template
@@ -0,0 +1,2 @@
+purpose to more-specifically override TF-Fuzz's expected result;
+read sst name napoleon chk "this won't work" exp generic_error;
diff --git a/tf_fuzz/regression/000022_SST_offset/check.py b/tf_fuzz/regression/000022_SST_offset/check.py
new file mode 100644
index 0000000..2027be8
--- /dev/null
+++ b/tf_fuzz/regression/000022_SST_offset/check.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+'''
+ Please read .../tf_fuzz/regression/README to understand this code.
+
+ Please also read the comments in .../tf_fuzz/regression/regress_lib/line_by_line.py.
+'''
+
+import sys, os, re, string, pdb
+sys.path.append ("../regress_lib")
+import line_by_line
+
+
+# Describe script usage:
+def usage():
+ print ('''
+ Command-line parameters:
+ 1. The test-template file, nominally named "template",
+ 2. The expected combined stdout/stderr output, nominally named "exp_stdout_stderr",
+ 3. The actual/generated combined stdout/stderr output, nominally named "stdout_stderr",
+ 4. The expected .c test file, nominally named "exp_test.c", and
+ 5. The actual, generated .c test file, nominally named "test.c".
+
+ Optionally, *before* these five arguments, you may add switches thus:
+ "--v" for verbose mode, to view line-by-line comparisons actual vs. expected,
+ "--q" to only print error messages and a successful-completion message,
+ "--qq" same as --q but not even printing out the completion message, and
+ "--s 12345" to run TF-Fuzz with seed value 12345 (or whatever).
+ ''')
+
+
+def main():
+ # See if we're supposed to be quiet:
+ loud = quiet = ultra_quiet = False
+ seed = ""
+ while sys.argv[1][0] == "-":
+ if sys.argv[1] == "--v":
+ loud = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--q":
+ quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--qq":
+ quiet = ultra_quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--s":
+ sys.argv.pop(1)
+ seed = sys.argv[1]
+ sys.argv.pop(1)
+ if not seed.isnumeric():
+ print ('The --s seed argument was not a number.')
+ usage()
+ sys.exit(1)
+
+ # Run TF-Fuzz:
+ if not quiet: print ("Running TF-Fuzz... ")
+ os.system ('rm -f stdout_stderr test.c')
+ command = '../../tfz -v ./' + sys.argv[1] + ' ./' + sys.argv[5]
+ command += ' ' + seed + ' >' + sys.argv[3] + ' 2>&1'
+ if loud:
+ print (command)
+ if os.system (command) == 0:
+ if not quiet: print ("TF-Fuzz run complete.")
+ else:
+ print ('Could not run TF-Fuzz; please see stdout_stderr file.')
+ sys.exit(2)
+
+ # Attempt to open files indicated on command line:
+ if len(sys.argv) != 6:
+ message = '{} requires 5 command-line arguments. Exiting.'
+ print (message.format(sys.argv[0]), file=sys.stderr)
+ usage()
+ sys.exit(3)
+ template_file_name = sys.argv[1]
+ exp_stdout_file_name = sys.argv[2]
+ act_stdout_file_name = sys.argv[3]
+ exp_test_file_name = sys.argv[4]
+ act_test_file_name = sys.argv[5]
+
+ try:
+ template_file = open (template_file_name, 'rt')
+ exp_stdout_file = open (exp_stdout_file_name, 'rt')
+ act_stdout_file = open (act_stdout_file_name, 'rt')
+ exp_test_file = open (exp_test_file_name, 'rt')
+ act_test_file = open (act_test_file_name, 'rt')
+ except FileNotFoundError:
+ print ('One or more files could not be found.')
+ usage();
+ sys.exit(4)
+ except:
+ print ('Something went wrong trying to open the input files.')
+ usage();
+ sys.exit(5)
+ else:
+ message = '\nInput files:\n {},\n {},\n {},\n'
+ message += ' {}, and\n {}\nopened successfully.\n'
+ if not quiet:
+ print (message.format (template_file_name, exp_stdout_file_name,
+ act_stdout_file_name, exp_test_file_name, act_test_file_name))
+
+ # Check it all:
+ if not quiet: print ("\nChecking test C file: ", end="")
+ line_by_line.check_file ( exp_test_file, exp_test_file_name,
+ act_test_file, act_test_file_name,
+ loud, quiet, ultra_quiet )
+ if not quiet: print ("Checking stdout and stderr: ", end="")
+ line_by_line.check_file ( exp_stdout_file, exp_stdout_file_name,
+ act_stdout_file, act_stdout_file_name,
+ loud, quiet, ultra_quiet )
+
+ # Ran to completion normally, so pass:
+ if not ultra_quiet: print ("Regression test passed.")
+ sys.exit(0)
+
+if __name__ == "__main__": main()
diff --git a/tf_fuzz/regression/000022_SST_offset/exp_stdout_stderr b/tf_fuzz/regression/000022_SST_offset/exp_stdout_stderr
new file mode 100644
index 0000000..c9d1a0f
--- /dev/null
+++ b/tf_fuzz/regression/000022_SST_offset/exp_stdout_stderr
@@ -0,0 +1,35 @@
+Trusted Firmware Fuzzer (TF-Fuzz) starting...
+
+Info: random seed was not specified.
+
+Using seed value of \d+ \(0x[a-f\d]+\).
+Purpose line: to set an offset on psa_ps_get()
+ASSET_IDENTIFIER: "whoNose"
+Asset identifier list: "data"
+Create from random data
+Set SST command: ";"
+Appended to end of call sequence: SST-set call.
+Set command: ";"
+Command with no expect: ";"
+ASSET_IDENTIFIER: "whoNose"
+Asset identifier list: "print"
+Read log to test log: "print"
+SST-data offset: "10"
+SST data offset
+10"
+SST-read arguments: 10"
+Read SST command: "10"
+Appended to end of call sequence: SST-get call.
+Read command: "10"
+Command with no expect: ";"
+Lines: Line number 4.
+Lines: Line number 4.
+Lines: Line number 4.
+Call sequence generated.
+Simulating call sequence...
+Call sequence:
+ SST-set call for asset whoNose
+ SST-get call for asset whoNose
+Writing test file, ./test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tf_fuzz/regression/000022_SST_offset/exp_test.c b/tf_fuzz/regression/000022_SST_offset/exp_test.c
new file mode 100644
index 0000000..03523dc
--- /dev/null
+++ b/tf_fuzz/regression/000022_SST_offset/exp_test.c
@@ -0,0 +1,70 @@
+/*
+ * Test purpose:
+ * to set an offset on psa_ps_get()
+ *
+ */
+
+#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 "tfm_memory_utils.h"
+#include "psa/crypto.h"
+#include "psa/crypto_sizes.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;
+ /* Variables (etc.) to initialize and check PSA assets: */
+ static uint8_t whoNose_set_data\[\] = "@@012@10@@[a-z\ ]*[\.\?\!]";
+ static uint32_t whoNose_set_length = \d+;
+ static uint8_t whoNose_act_data\[2048\] = "[A-Z][a-z\ ]*[\.\?\!]";
+ static size_t whoNose_act_length = \d+;
+ (void)sst_status;
+ /* "void" to prevent unused-variable warning, since the variable may not
+ * be used in this particular test case.
+ */
+
+ crypto_status = psa_crypto_init();
+ if (crypto_status != PSA_SUCCESS) {
+ TEST_FAIL("Could not initialize Crypto.");
+ return;
+ }
+
+ TEST_LOG("Test to set an offset on psa_ps_get()");
+
+
+ /* PSA calls to test: */
+ /\* Creating SST asset "whoNose," with data "@@012@10@@...". \*/
+ sst_status = psa_ps_set\(@@@001@@@, whoNose_set_length, whoNose_set_data,
+ PSA_STORAGE_FLAG_[A-Z_]+\);
+ if (sst_status != PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+ return;
+ }
+ sst_status = psa_ps_get\(@@@001@@@, 10, \d+, whoNose_act_data,
+ &whoNose_act_length);
+ if (sst_status != PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_get() expected PSA_SUCCESS.");
+ return;
+ }
+ TEST_LOG\(\"whoNose_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/tf_fuzz/regression/000022_SST_offset/template b/tf_fuzz/regression/000022_SST_offset/template
new file mode 100644
index 0000000..9fa46e9
--- /dev/null
+++ b/tf_fuzz/regression/000022_SST_offset/template
@@ -0,0 +1,3 @@
+purpose to set an offset on psa_ps_get();
+set sst name whoNose data *;
+read sst name whoNose print offset 10;
diff --git a/tf_fuzz/regression/000023_SST_creation_flags/check.py b/tf_fuzz/regression/000023_SST_creation_flags/check.py
new file mode 100644
index 0000000..2027be8
--- /dev/null
+++ b/tf_fuzz/regression/000023_SST_creation_flags/check.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+'''
+ Please read .../tf_fuzz/regression/README to understand this code.
+
+ Please also read the comments in .../tf_fuzz/regression/regress_lib/line_by_line.py.
+'''
+
+import sys, os, re, string, pdb
+sys.path.append ("../regress_lib")
+import line_by_line
+
+
+# Describe script usage:
+def usage():
+ print ('''
+ Command-line parameters:
+ 1. The test-template file, nominally named "template",
+ 2. The expected combined stdout/stderr output, nominally named "exp_stdout_stderr",
+ 3. The actual/generated combined stdout/stderr output, nominally named "stdout_stderr",
+ 4. The expected .c test file, nominally named "exp_test.c", and
+ 5. The actual, generated .c test file, nominally named "test.c".
+
+ Optionally, *before* these five arguments, you may add switches thus:
+ "--v" for verbose mode, to view line-by-line comparisons actual vs. expected,
+ "--q" to only print error messages and a successful-completion message,
+ "--qq" same as --q but not even printing out the completion message, and
+ "--s 12345" to run TF-Fuzz with seed value 12345 (or whatever).
+ ''')
+
+
+def main():
+ # See if we're supposed to be quiet:
+ loud = quiet = ultra_quiet = False
+ seed = ""
+ while sys.argv[1][0] == "-":
+ if sys.argv[1] == "--v":
+ loud = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--q":
+ quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--qq":
+ quiet = ultra_quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--s":
+ sys.argv.pop(1)
+ seed = sys.argv[1]
+ sys.argv.pop(1)
+ if not seed.isnumeric():
+ print ('The --s seed argument was not a number.')
+ usage()
+ sys.exit(1)
+
+ # Run TF-Fuzz:
+ if not quiet: print ("Running TF-Fuzz... ")
+ os.system ('rm -f stdout_stderr test.c')
+ command = '../../tfz -v ./' + sys.argv[1] + ' ./' + sys.argv[5]
+ command += ' ' + seed + ' >' + sys.argv[3] + ' 2>&1'
+ if loud:
+ print (command)
+ if os.system (command) == 0:
+ if not quiet: print ("TF-Fuzz run complete.")
+ else:
+ print ('Could not run TF-Fuzz; please see stdout_stderr file.')
+ sys.exit(2)
+
+ # Attempt to open files indicated on command line:
+ if len(sys.argv) != 6:
+ message = '{} requires 5 command-line arguments. Exiting.'
+ print (message.format(sys.argv[0]), file=sys.stderr)
+ usage()
+ sys.exit(3)
+ template_file_name = sys.argv[1]
+ exp_stdout_file_name = sys.argv[2]
+ act_stdout_file_name = sys.argv[3]
+ exp_test_file_name = sys.argv[4]
+ act_test_file_name = sys.argv[5]
+
+ try:
+ template_file = open (template_file_name, 'rt')
+ exp_stdout_file = open (exp_stdout_file_name, 'rt')
+ act_stdout_file = open (act_stdout_file_name, 'rt')
+ exp_test_file = open (exp_test_file_name, 'rt')
+ act_test_file = open (act_test_file_name, 'rt')
+ except FileNotFoundError:
+ print ('One or more files could not be found.')
+ usage();
+ sys.exit(4)
+ except:
+ print ('Something went wrong trying to open the input files.')
+ usage();
+ sys.exit(5)
+ else:
+ message = '\nInput files:\n {},\n {},\n {},\n'
+ message += ' {}, and\n {}\nopened successfully.\n'
+ if not quiet:
+ print (message.format (template_file_name, exp_stdout_file_name,
+ act_stdout_file_name, exp_test_file_name, act_test_file_name))
+
+ # Check it all:
+ if not quiet: print ("\nChecking test C file: ", end="")
+ line_by_line.check_file ( exp_test_file, exp_test_file_name,
+ act_test_file, act_test_file_name,
+ loud, quiet, ultra_quiet )
+ if not quiet: print ("Checking stdout and stderr: ", end="")
+ line_by_line.check_file ( exp_stdout_file, exp_stdout_file_name,
+ act_stdout_file, act_stdout_file_name,
+ loud, quiet, ultra_quiet )
+
+ # Ran to completion normally, so pass:
+ if not ultra_quiet: print ("Regression test passed.")
+ sys.exit(0)
+
+if __name__ == "__main__": main()
diff --git a/tf_fuzz/regression/000023_SST_creation_flags/exp_stdout_stderr b/tf_fuzz/regression/000023_SST_creation_flags/exp_stdout_stderr
new file mode 100644
index 0000000..2b6ab80
--- /dev/null
+++ b/tf_fuzz/regression/000023_SST_creation_flags/exp_stdout_stderr
@@ -0,0 +1,89 @@
+Trusted Firmware Fuzzer (TF-Fuzz) starting...
+
+Info: random seed was not specified.
+
+Using seed value of \d+ \(0x[a-f\d]+\).
+Purpose line: to set SST creation flags
+ASSET_IDENTIFIER: "hasCF"
+Asset identifier list: "data"
+LITERAL string: "this asset has write-once"
+Create from literal data: ""this asset has write-once""
+SST write-once flag: write_once"
+SST creation flag
+;"
+SST creation flags
+;"
+Set SST command: ";"
+Appended to end of call sequence: SST-set call.
+Set command: ";"
+Command with no expect: ";"
+ASSET_IDENTIFIER: "hasCF2"
+Asset identifier list: "data"
+LITERAL string: "this asset has also write-once"
+Create from literal data: ""this asset has also write-once""
+SST write-once flag: wo"
+SST creation flag
+;"
+SST creation flags
+;"
+Set SST command: ";"
+Appended to end of call sequence: SST-set call.
+Set command: ";"
+Command with no expect: ";"
+ASSET_IDENTIFIER: "alsoHasCF"
+Asset identifier list: "data"
+LITERAL string: "this asset has no flags"
+Create from literal data: ""this asset has no flags""
+SST no storage flag: none"
+SST creation flag
+expect"
+SST creation flags
+expect"
+Set SST command: "expect"
+Appended to end of call sequence: SST-set call.
+Set command: "expect"
+Expect pass clause: "pass"
+Command with expect: ";"
+ASSET_IDENTIFIER: "alsoHasCF2"
+Asset identifier list: "data"
+LITERAL string: "this asset has NO_CONFIDENTIALITY"
+Create from literal data: ""this asset has NO_CONFIDENTIALITY""
+SST no-confidentiality flag: ncf"
+SST creation flag
+;"
+SST creation flags
+;"
+Set SST command: ";"
+Appended to end of call sequence: SST-set call.
+Set command: ";"
+Command with no expect: ";"
+ASSET_IDENTIFIER: "yetAnother"
+Asset identifier list: "data"
+LITERAL string: "this asset has NO_REPLAY_PROTECTION"
+Create from literal data: ""this asset has NO_REPLAY_PROTECTION""
+SST no-replay-protection flag: nrp"
+SST creation flag
+;"
+SST creation flags
+;"
+Set SST command: ";"
+Appended to end of call sequence: SST-set call.
+Set command: ";"
+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.
+Call sequence generated.
+Simulating call sequence...
+Call sequence:
+ SST-set call for asset hasCF
+ SST-set call for asset hasCF2
+ SST-set call for asset alsoHasCF
+ SST-set call for asset alsoHasCF2
+ SST-set call for asset yetAnother
+Writing test file, ./test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tf_fuzz/regression/000023_SST_creation_flags/exp_test.c b/tf_fuzz/regression/000023_SST_creation_flags/exp_test.c
new file mode 100644
index 0000000..9dbe4cf
--- /dev/null
+++ b/tf_fuzz/regression/000023_SST_creation_flags/exp_test.c
@@ -0,0 +1,117 @@
+/*
+ * Test purpose:
+ * to set SST creation flags
+ *
+ */
+
+#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 "tfm_memory_utils.h"
+#include "psa/crypto.h"
+#include "psa/crypto_sizes.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;
+ /* Variables (etc.) to initialize and check PSA assets: */
+ static uint8_t hasCF_set_data[] = "this asset has write-once";
+ static uint32_t hasCF_set_length = 25;
+ static uint8_t hasCF2_set_data[] = "this asset has also write-once";
+ static uint32_t hasCF2_set_length = 30;
+ static uint8_t alsoHasCF_set_data[] = "this asset has no flags";
+ static uint32_t alsoHasCF_set_length = 23;
+ static uint8_t alsoHasCF2_set_data[] = "this asset has NO_CONFIDENTIALITY";
+ static uint32_t alsoHasCF2_set_length = 33;
+ static uint8_t yetAnother_set_data[] = "this asset has NO_REPLAY_PROTECTION";
+ static uint32_t yetAnother_set_length = 35;
+ (void)sst_status;
+ /* "void" to prevent unused-variable warning, since the variable may not
+ * be used in this particular test case.
+ */
+
+ crypto_status = psa_crypto_init();
+ if (crypto_status != PSA_SUCCESS) {
+ TEST_FAIL("Could not initialize Crypto.");
+ return;
+ }
+
+ TEST_LOG("Test to set SST creation flags");
+
+
+ /* PSA calls to test: */
+ /* Creating SST asset "hasCF," with data "this asset...". */
+ sst_status = psa_ps_set\(@@@001@@@, hasCF_set_length, hasCF_set_data,
+ PSA_STORAGE_FLAG_WRITE_ONCE);
+ if (sst_status != PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+ return;
+ }
+ /* Creating SST asset "hasCF2," with data "this asset...". */
+ sst_status = psa_ps_set\(@@@002@@@, hasCF2_set_length, hasCF2_set_data,
+ PSA_STORAGE_FLAG_WRITE_ONCE);
+ if (sst_status != PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+ return;
+ }
+ /* Creating SST asset "alsoHasCF," with data "this asset...". */
+ sst_status = psa_ps_set\(@@@003@@@, alsoHasCF_set_length, alsoHasCF_set_data,
+ PSA_STORAGE_FLAG_NONE);
+ if (sst_status != PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+ return;
+ }
+ /* Creating SST asset "alsoHasCF2," with data "this asset...". */
+ sst_status = psa_ps_set\(@@@004@@@, alsoHasCF2_set_length, alsoHasCF2_set_data,
+ PSA_STORAGE_FLAG_NO_CONFIDENTIALITY);
+ if (sst_status != PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+ return;
+ }
+ /* Creating SST asset "yetAnother," with data "this asset...". */
+ sst_status = psa_ps_set\(@@@005@@@, yetAnother_set_length, yetAnother_set_data,
+ PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION);
+ 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/tf_fuzz/regression/000023_SST_creation_flags/template b/tf_fuzz/regression/000023_SST_creation_flags/template
new file mode 100644
index 0000000..5cfa287
--- /dev/null
+++ b/tf_fuzz/regression/000023_SST_creation_flags/template
@@ -0,0 +1,6 @@
+purpose to set SST creation flags;
+set sst name hasCF data "this asset has write-once" flag write_once;
+set sst name hasCF2 data "this asset has also write-once" flag wo;
+set sst name alsoHasCF data "this asset has no flags" flag none expect pass;
+set sst name alsoHasCF2 data "this asset has NO_CONFIDENTIALITY" flag ncf;
+set sst name yetAnother data "this asset has NO_REPLAY_PROTECTION" flag nrp;
diff --git a/tf_fuzz/regression/000024_SST_write_once/check.py b/tf_fuzz/regression/000024_SST_write_once/check.py
new file mode 100644
index 0000000..2027be8
--- /dev/null
+++ b/tf_fuzz/regression/000024_SST_write_once/check.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+'''
+ Please read .../tf_fuzz/regression/README to understand this code.
+
+ Please also read the comments in .../tf_fuzz/regression/regress_lib/line_by_line.py.
+'''
+
+import sys, os, re, string, pdb
+sys.path.append ("../regress_lib")
+import line_by_line
+
+
+# Describe script usage:
+def usage():
+ print ('''
+ Command-line parameters:
+ 1. The test-template file, nominally named "template",
+ 2. The expected combined stdout/stderr output, nominally named "exp_stdout_stderr",
+ 3. The actual/generated combined stdout/stderr output, nominally named "stdout_stderr",
+ 4. The expected .c test file, nominally named "exp_test.c", and
+ 5. The actual, generated .c test file, nominally named "test.c".
+
+ Optionally, *before* these five arguments, you may add switches thus:
+ "--v" for verbose mode, to view line-by-line comparisons actual vs. expected,
+ "--q" to only print error messages and a successful-completion message,
+ "--qq" same as --q but not even printing out the completion message, and
+ "--s 12345" to run TF-Fuzz with seed value 12345 (or whatever).
+ ''')
+
+
+def main():
+ # See if we're supposed to be quiet:
+ loud = quiet = ultra_quiet = False
+ seed = ""
+ while sys.argv[1][0] == "-":
+ if sys.argv[1] == "--v":
+ loud = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--q":
+ quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--qq":
+ quiet = ultra_quiet = True
+ sys.argv.pop(1)
+ elif sys.argv[1] == "--s":
+ sys.argv.pop(1)
+ seed = sys.argv[1]
+ sys.argv.pop(1)
+ if not seed.isnumeric():
+ print ('The --s seed argument was not a number.')
+ usage()
+ sys.exit(1)
+
+ # Run TF-Fuzz:
+ if not quiet: print ("Running TF-Fuzz... ")
+ os.system ('rm -f stdout_stderr test.c')
+ command = '../../tfz -v ./' + sys.argv[1] + ' ./' + sys.argv[5]
+ command += ' ' + seed + ' >' + sys.argv[3] + ' 2>&1'
+ if loud:
+ print (command)
+ if os.system (command) == 0:
+ if not quiet: print ("TF-Fuzz run complete.")
+ else:
+ print ('Could not run TF-Fuzz; please see stdout_stderr file.')
+ sys.exit(2)
+
+ # Attempt to open files indicated on command line:
+ if len(sys.argv) != 6:
+ message = '{} requires 5 command-line arguments. Exiting.'
+ print (message.format(sys.argv[0]), file=sys.stderr)
+ usage()
+ sys.exit(3)
+ template_file_name = sys.argv[1]
+ exp_stdout_file_name = sys.argv[2]
+ act_stdout_file_name = sys.argv[3]
+ exp_test_file_name = sys.argv[4]
+ act_test_file_name = sys.argv[5]
+
+ try:
+ template_file = open (template_file_name, 'rt')
+ exp_stdout_file = open (exp_stdout_file_name, 'rt')
+ act_stdout_file = open (act_stdout_file_name, 'rt')
+ exp_test_file = open (exp_test_file_name, 'rt')
+ act_test_file = open (act_test_file_name, 'rt')
+ except FileNotFoundError:
+ print ('One or more files could not be found.')
+ usage();
+ sys.exit(4)
+ except:
+ print ('Something went wrong trying to open the input files.')
+ usage();
+ sys.exit(5)
+ else:
+ message = '\nInput files:\n {},\n {},\n {},\n'
+ message += ' {}, and\n {}\nopened successfully.\n'
+ if not quiet:
+ print (message.format (template_file_name, exp_stdout_file_name,
+ act_stdout_file_name, exp_test_file_name, act_test_file_name))
+
+ # Check it all:
+ if not quiet: print ("\nChecking test C file: ", end="")
+ line_by_line.check_file ( exp_test_file, exp_test_file_name,
+ act_test_file, act_test_file_name,
+ loud, quiet, ultra_quiet )
+ if not quiet: print ("Checking stdout and stderr: ", end="")
+ line_by_line.check_file ( exp_stdout_file, exp_stdout_file_name,
+ act_stdout_file, act_stdout_file_name,
+ loud, quiet, ultra_quiet )
+
+ # Ran to completion normally, so pass:
+ if not ultra_quiet: print ("Regression test passed.")
+ sys.exit(0)
+
+if __name__ == "__main__": main()
diff --git a/tf_fuzz/regression/000024_SST_write_once/exp_stdout_stderr b/tf_fuzz/regression/000024_SST_write_once/exp_stdout_stderr
new file mode 100644
index 0000000..2273c23
--- /dev/null
+++ b/tf_fuzz/regression/000024_SST_write_once/exp_stdout_stderr
@@ -0,0 +1,45 @@
+Trusted Firmware Fuzzer (TF-Fuzz) starting...
+
+Info: random seed was not specified.
+
+Using seed value of \d+ \(0x[a-f\d]+\).
+Purpose line: to verify we can't write multiple times to a write-once SST asset
+ASSET_IDENTIFIER: "writeOnce"
+Asset identifier list: "data"
+Create from random data
+SST write-once flag: wo"
+SST creation flag
+;"
+SST creation flags
+;"
+Set SST command: ";"
+Appended to end of call sequence: SST-set call.
+Set command: ";"
+Command with no expect: ";"
+ASSET_IDENTIFIER: "writeOnce"
+Asset identifier list: "data"
+Create from random data
+Set SST command: ";"
+Appended to end of call sequence: SST-set call.
+Set command: ";"
+Command with no expect: ";"
+ASSET_IDENTIFIER: "writeOnce"
+Asset identifier list: "data"
+Create from random data
+Set SST command: ";"
+Appended to end of call sequence: SST-set call.
+Set command: ";"
+Command with no expect: ";"
+Lines: Line number 5.
+Lines: Line number 5.
+Lines: Line number 5.
+Lines: Line number 5.
+Call sequence generated.
+Simulating call sequence...
+Call sequence:
+ SST-set call for asset writeOnce
+ SST-set call for asset writeOnce
+ SST-set call for asset writeOnce
+Writing test file, ./test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tf_fuzz/regression/000024_SST_write_once/exp_test.c b/tf_fuzz/regression/000024_SST_write_once/exp_test.c
new file mode 100644
index 0000000..02d0530
--- /dev/null
+++ b/tf_fuzz/regression/000024_SST_write_once/exp_test.c
@@ -0,0 +1,79 @@
+/*
+ * Test purpose:
+ * to verify we can't write multiple times to a write-once 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 "tfm_memory_utils.h"
+#include "psa/crypto.h"
+#include "psa/crypto_sizes.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;
+ /* Variables (etc.) to initialize and check PSA assets: */
+ static uint8_t writeOnce_set_data\[\] = "@@012@10@@[a-z\ ]*[\.\?\!]";
+ static uint32_t writeOnce_set_length = \d+;
+ static uint8_t writeOnce_set_data_1\[\] = "@@013@10@@[a-z\ ]*[\.\?\!]";
+ static uint32_t writeOnce_set_length_1 = \d+;
+ static uint8_t writeOnce_set_data_2\[\] = "@@014@10@@[a-z\ ]*[\.\?\!]";
+ static uint32_t writeOnce_set_length_2 = \d+;
+ (void)sst_status;
+ /* "void" to prevent unused-variable warning, since the variable may not
+ * be used in this particular test case.
+ */
+
+ crypto_status = psa_crypto_init();
+ if (crypto_status != PSA_SUCCESS) {
+ TEST_FAIL("Could not initialize Crypto.");
+ return;
+ }
+
+ TEST_LOG("Test to verify we can't write multiple times to a write-once SST asset");
+
+
+ /* PSA calls to test: */
+ /\* Creating SST asset "writeOnce," with data "@@012@10@@...". \*/
+ sst_status = psa_ps_set\(@@@001@@@, writeOnce_set_length, writeOnce_set_data,
+ PSA_STORAGE_FLAG_WRITE_ONCE);
+ if (sst_status != PSA_SUCCESS) {
+ TEST_FAIL("psa_ps_set() expected PSA_SUCCESS.");
+ return;
+ }
+ /\* Resetting SST asset "writeOnce," with data "@@013@10@@...". \*/
+ sst_status = psa_ps_set\(@@@001@@@, writeOnce_set_length_1, writeOnce_set_data_1,
+ PSA_STORAGE_FLAG_WRITE_ONCE);
+ if (sst_status != PSA_ERROR_NOT_PERMITTED) {
+ TEST_FAIL("psa_ps_set() expected PSA_ERROR_NOT_PERMITTED.");
+ return;
+ }
+ /\* Resetting SST asset "writeOnce," with data "@@014@10@@...". \*/
+ sst_status = psa_ps_set\(@@@001@@@, writeOnce_set_length_2, writeOnce_set_data_2,
+ PSA_STORAGE_FLAG_WRITE_ONCE);
+ if (sst_status != PSA_ERROR_NOT_PERMITTED) {
+ TEST_FAIL("psa_ps_set() expected PSA_ERROR_NOT_PERMITTED.");
+ 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/tf_fuzz/regression/000024_SST_write_once/template b/tf_fuzz/regression/000024_SST_write_once/template
new file mode 100644
index 0000000..60fc978
--- /dev/null
+++ b/tf_fuzz/regression/000024_SST_write_once/template
@@ -0,0 +1,4 @@
+purpose to verify we can't write multiple times to a write-once SST asset;
+set sst name writeOnce data * flag wo;
+set sst name writeOnce data *;
+set sst name writeOnce data *;
diff --git a/tf_fuzz/regression/README b/tf_fuzz/regression/README
new file mode 100644
index 0000000..d4fbcb6
--- /dev/null
+++ b/tf_fuzz/regression/README
@@ -0,0 +1,9 @@
+This is a regression suite for the TF-Fuzz tool.
+
+For more information, please browse to:
+
+ https://ci.trustedfirmware.org/job/tf-m-build-test-nightly/lastSuccessfulBuild/artifact/build-docs/tf-m_documents/install/doc/user_guide/html/docs/user_guides/tf_fuzz/~regression_dir.html
+
+--------------
+
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
diff --git a/tf_fuzz/regression/add_these_tests/000015_set_sst_multi_name_remove_rand_active/exp_stdout_stderr b/tf_fuzz/regression/add_these_tests/000015_set_sst_multi_name_remove_rand_active/exp_stdout_stderr
new file mode 100644
index 0000000..3c5de35
--- /dev/null
+++ b/tf_fuzz/regression/add_these_tests/000015_set_sst_multi_name_remove_rand_active/exp_stdout_stderr
@@ -0,0 +1,30 @@
+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"
+Asset identifier list: "data"
+LITERAL string: "read my lips"
+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.
+Call sequence generated.
+Simulating call sequence...
+Writing test file, ./test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tf_fuzz/regression/add_these_tests/000015_set_sst_multi_name_remove_rand_active/exp_test.c b/tf_fuzz/regression/add_these_tests/000015_set_sst_multi_name_remove_rand_active/exp_test.c
new file mode 100644
index 0000000..c0eddcd
--- /dev/null
+++ b/tf_fuzz/regression/add_these_tests/000015_set_sst_multi_name_remove_rand_active/exp_test.c
@@ -0,0 +1,117 @@
+/*
+ * 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 "tfm_memory_utils.h"
+#include "psa/crypto.h"
+#include "psa/crypto_sizes.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;
+ /* Variables (etc.) to initialize and check PSA assets: */
+ static uint8_t president_set_data[] = "read my lips";
+ int president_set_length = 12;
+ static uint8_t george_set_data[] = "read my lips";
+ int george_set_length = 12;
+ static uint8_t herbert_set_data[] = "read my lips";
+ int herbert_set_length = 12;
+ static uint8_t walker_set_data[] = "read my lips";
+ int walker_set_length = 12;
+ static uint8_t bush_set_data[] = "read my lips";
+ int bush_set_length = 12;
+
+ 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");
+
+
+
+
+ /* PSA calls to test: */
+
+ /* Creating SST asset "president," with data "read my li...". */
+ sst_status = psa_ps_set(@@@001@@@, president_set_length, 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_set_length, 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_set_length, 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_set_length, 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_set_length, 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/tf_fuzz/regression/add_these_tests/000015_set_sst_multi_name_remove_rand_active/template b/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/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/tf_fuzz/regression/add_these_tests/000016_set_sst_multi_name_remove_multi_rand_active_remove_rand_deleted/exp_stdout_stderr b/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..bdeffb7
--- /dev/null
+++ b/tf_fuzz/regression/add_these_tests/000016_set_sst_multi_name_remove_multi_rand_active_remove_rand_deleted/exp_stdout_stderr
@@ -0,0 +1,48 @@
+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"
+Asset identifier list: "data"
+LITERAL string: "no new taxes"
+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.
+Call sequence generated.
+Simulating call sequence...
+Writing test file, ./test.c.
+
+TF-Fuzz test generation complete.
diff --git a/tf_fuzz/regression/add_these_tests/000016_set_sst_multi_name_remove_multi_rand_active_remove_rand_deleted/exp_test.c b/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..c2752fb
--- /dev/null
+++ b/tf_fuzz/regression/add_these_tests/000016_set_sst_multi_name_remove_multi_rand_active_remove_rand_deleted/exp_test.c
@@ -0,0 +1,123 @@
+/*
+ * 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 "tfm_memory_utils.h"
+#include "psa/crypto.h"
+#include "psa/crypto_sizes.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;
+ /* Variables (etc.) to initialize and check PSA assets: */
+ static uint8_t president_set_data[] = "no new taxes";
+ int president_set_length = 12;
+ static uint8_t george_set_data[] = "no new taxes";
+ int george_set_length = 12;
+ static uint8_t herbert_set_data[] = "no new taxes";
+ int herbert_set_length = 12;
+ static uint8_t walker_set_data[] = "no new taxes";
+ int walker_set_length = 12;
+ static uint8_t bush_set_data[] = "no new taxes";
+ int bush_set_length = 12;
+
+ 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");
+
+
+
+
+ /* PSA calls to test: */
+
+ /* Creating SST asset "president," with data "no new tax...". */
+ sst_status = psa_ps_set(4713, president_set_length, president_set_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_set_length, 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_set_length, 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_set_length, 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_set_length, 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/tf_fuzz/regression/add_these_tests/000016_set_sst_multi_name_remove_multi_rand_active_remove_rand_deleted/template b/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..2bf82b0
--- /dev/null
+++ b/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
+rm sst *active; // remove *some other* active asset
+rm sst *act; // remove *yet another* active asset
+remove sst *del; // attempt to remove some asset that's already been removed
diff --git a/tf_fuzz/regression/regress b/tf_fuzz/regression/regress
new file mode 100644
index 0000000..1a2b595
--- /dev/null
+++ b/tf_fuzz/regression/regress
@@ -0,0 +1,22 @@
+# 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
+ echo Running "$reg_test"...
+ cd $reg_test
+ rm -f test.c stdout_stderr
+ python3 check.py --q template exp_stdout_stderr stdout_stderr exp_test.c test.c
+ if test $? -ne 0
+ then
+ exit
+ fi
+ cd ..
+done
+echo
+echo
+echo All TF-Fuzz regression tests passed.
diff --git a/tf_fuzz/regression/regress_lib/line_by_line.py b/tf_fuzz/regression/regress_lib/line_by_line.py
new file mode 100644
index 0000000..f09a038
--- /dev/null
+++ b/tf_fuzz/regression/regress_lib/line_by_line.py
@@ -0,0 +1,172 @@
+#!/usr/bin/env python3
+# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+'''
+The functions here perform straight-forward line-by-line comparisons of regression
+TF-Fuzz regression tests. These are not sufficient to address cases where the PSA
+calls are randomized.
+
+Each given line of the expected files (exp_stdout_stderr and exp_test.c) functions
+as Python regex for the corresonding line in the actual/generated corresponding
+file. Actually, the expected-file lines may need a little bit of tweaking first.
+There are three scenarios:
+* The line in exp_* file contains no regex content at all. In this case, the two
+ lines must be exactly identical, character for character. The actual/generated
+ output files do not contain regexes, but can contain parentheses or other
+ characters that "look like" regex content, and thus confuse re.match(). So,
+ it's first checked for an exact string == match.
+* The line in the exp_* file contains one or more standard-Python regex patterns
+ to match. In this case, a Python re.match() will still report a match.
+* The line in the exp_* file contains one or more non-standard regex pattern, in
+ which case that non-standard regex pattern needs to be replaced with the actual,
+ expected character string.
+
+As described in the above-cited README, these non-standard regex wildcards in the
+exp_* files take either of two formats:
+* "@@@" a 3-digit pattern number "@@@" (e.g., "@@@005@@@"): This denotes a
+ pattern of no particular length that must match the same text every occurrence
+ in the actual/generated file.
+* "@@" a 3-digit pattern number "@" a 2-digit length in chars "@@": Same idea as
+ the previous pattern, except that it also has a specific length.
+
+To address these special regex wildcards, check_gen_test() below has to:
+1. Isolate the wildcard from the rest of the string,
+2. Check that wildcard against a Python dictionary relating the wildcard name to
+ its expected-text substitution value,
+3. If not present in the dictionary, create a new dictionary entry relating the
+ wildcard text to the text found in that spot in the actual/generated file,
+4. Replace that wildcard text with the expected value from the hash, then
+5. As with all lines, perform the re.match() between the two lines.
+'''
+
+import sys, os, re, string, pdb
+
+
+'''
+mask_other_wildcards(), used by resolve_wildcards() below, is used in harvesting
+the value of a certain wildcard of the sort described above. After the caller
+replaces the wildcard of interest with a regex to retrieve that data from actual-
+output file, it passes the string into here, to replace all other wildcards with
+"anything goes" regexes.
+'''
+def mask_other_wildcards (a_string):
+ # Unsized wildcards:
+ while True:
+ matchInfo = re.match ('.*(@@@\d\d\d@@@)', a_string)
+ if not matchInfo:
+ break
+ wildcard = matchInfo.group(1)
+ a_string = a_string.replace (wildcard, '.*')
+ # Sized wildcards:
+ while True:
+ matchInfo = re.match ('.*(@@\d\d\d@\d\d@@)', a_string)
+ if not matchInfo:
+ break
+ wildcard = matchInfo.group(1)
+ a_string = a_string.replace (wildcard, '.*')
+ return a_string
+
+
+'''
+resolve_wildcards() resolves wildcards of the sort described above, in an expected
+file line (exp) from a wildcard dictionary (wildcard_dict). In particular, it
+replaces them with what the wildcards are found to stand for in the actual test
+output (act). If it encounters a wildcard it has not seen before, it adds it to
+the dictionary, based upon what's in the test.c output. Further occurrences of that
+wildcard, it pulls from the wildcard dictionary, meaning that the subsequent
+occurrences must resolve to the same text string.
+'''
+def resolve_wildcards (exp, act, wildcard_dict):
+ # Loop through each wildcard on the line, filling them in with values from the
+ # wildcard dictionary, or filling them into the wildcard dictionary.
+
+ #pdb.set_trace()
+
+ while True:
+ wildcard_sized = False
+ matchInfo = re.match ('.*(@@@\d\d\d@@@)', exp)
+ if not matchInfo:
+ wildcard_sized = True
+ # 0 = sized, and we'll fill in that size below, if we don't already know
+ matchInfo = re.match ('.*(@@\d\d\d@\d\d@@)', exp)
+ if not matchInfo:
+ break
+ wildcard = matchInfo.group(1)
+ if wildcard in wildcard_dict:
+ # Previously-encountered wildcard:
+ wildcard_value = wildcard_dict[wildcard]
+ else:
+ # New wildcard:
+ if wildcard_sized: # find the size
+ size_str = re.match ("@@\d\d\d@(\d\d)@@",wildcard).group(1)
+ find_sub = exp.replace (wildcard, '(.{' + size_str + '})', 1)
+ else:
+ find_sub = exp.replace (wildcard, '(.*)', 1)
+ find_sub = mask_other_wildcards (find_sub)
+ matchInfo = re.match (find_sub, act)
+ wildcard_value = matchInfo.group(1)
+ wildcard_dict[wildcard] = wildcard_value
+ exp = exp.replace (wildcard, wildcard_value)
+ return exp
+
+'''
+check_file() checks that an actual-output test file (act_test_file) matches an
+expected-output file (exp_test_file), line by line, including resolving the
+wildcards of the nature described above.
+'''
+def check_file ( exp_test_file, exp_test_file_name,
+ act_test_file, act_test_file_name,
+ loud, quiet, ultra_quiet ):
+ # This is the dictionary of wildcards, of the nature described above.
+ wildcard_dict = dict()
+
+ line_no = 0
+ while True:
+ exp_line = exp_test_file.readline()
+ act_line = act_test_file.readline()
+ # Ignore the special case where a seed was specified in generating actual,
+ # but wasn't in expected file:
+ if exp_line == 'Info: random seed was not specified.\n' and act_line == '\n':
+ print ("(Note: Ignoring no-seed-specified message in expected.)")
+ exp_line = exp_test_file.readline()
+ line_no += 1
+ if not quiet and not loud: print (".", end="")
+ if not exp_line and act_line:
+ message = "\nError: More lines in file {} than in {}."
+ if not ultra_quiet:
+ print (message.format(act_test_file_name, exp_test_file_name))
+ sys.exit(8)
+ elif not act_line and exp_line:
+ message = "\nError: More lines in file {} than in {}."
+ if not ultra_quiet:
+ print (message.format(exp_test_file_name, act_test_file_name))
+ sys.exit(9)
+ # No line-count mismatch (so far); either both reads succeeded or both failed:
+ if not exp_line:
+ break # all lines read; kick out of the loop.
+ exp_line = exp_line.rstrip(); act_line = act_line.rstrip()
+ if loud and not quiet:
+ print ("\n" + str(line_no) + "\nExpect: '" + exp_line + "'")
+ print ("Actual: '" + act_line + "'")
+ # If the two lines match as raw strings then we're good:
+ if exp_line == act_line:
+ pass # this line passes
+ else:
+ # Before doing a re.match() on this line pair, replace any nontraditional
+ # wildcards with what they're expected to contain:
+ if re.match (".*@@\d\d\d@", exp_line): # just to save time if no wildcards
+ exp_line = resolve_wildcards (exp_line, act_line, wildcard_dict)
+ if (exp_line == "" and act_line != "") or not re.match (exp_line, act_line):
+ message = "\nError: At line {} mismatch between {} and {}:"
+ message1 = " Expected: {}"
+ message2 = " Got: {}\n"
+ if not ultra_quiet:
+ print (message.format(line_no, exp_test_file_name, act_test_file_name))
+ print (message1.format(exp_line))
+ print (message2.format(act_line))
+ sys.exit(10)
+ if not quiet: print ("\nGenerated file complies with expected file.")
+
+
diff --git a/tf_fuzz/template/README b/tf_fuzz/template/README
new file mode 100644
index 0000000..3cfc309
--- /dev/null
+++ b/tf_fuzz/template/README
@@ -0,0 +1,10 @@
+These classes describe "tracker" objects for parsing test templates, and for
+generating PSA calls from them.
+
+For more information, please browse to:
+
+ https://ci.trustedfirmware.org/job/tf-m-build-test-nightly/lastSuccessfulBuild/artifact/build-docs/tf-m_documents/install/doc/user_guide/html/docs/user_guides/tf_fuzz/template_dir.html
+
+--------------
+
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
diff --git a/tf_fuzz/template/crypto_template_line.cpp b/tf_fuzz/template/crypto_template_line.cpp
new file mode 100644
index 0000000..3cf8a35
--- /dev/null
+++ b/tf_fuzz/template/crypto_template_line.cpp
@@ -0,0 +1,156 @@
+/*
+ * 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
+}
+
+// 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)
+{
+ return; // just to have something to pin a breakpoint onto
+}
+
+// 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.
+}
+
+// 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
+}
+
+// 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
+}
+
+// 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/tf_fuzz/template/crypto_template_line.hpp b/tf_fuzz/template/crypto_template_line.hpp
new file mode 100644
index 0000000..4626536
--- /dev/null
+++ b/tf_fuzz/template/crypto_template_line.hpp
@@ -0,0 +1,294 @@
+/*
+ * 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:
+ 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) {
+ /* If the name of the primary asset is known, then add calls at
+ random, otherwise append to end. If not, then we do not know
+ what asset-name barrier to search for. */
+ bool add_to_end_bool = (random_asset != psa_asset_usage::all);
+
+ // Add the calls of interest:
+ define_call<init_policy_call> (set_data, random_data,
+ fill_in_template, create_call, temLin, rsrc,
+ add_random_after_barrier, yes_set_barrier );
+ define_call<reset_policy_call> (set_data, random_data,
+ fill_in_template, create_call, temLin, rsrc,
+ add_random_after_barrier, yes_set_barrier );
+ policy_info.usage_string.assign ("0"); // clear out all usages
+ define_call<set_policy_usage_call> (set_data, random_data,
+ fill_in_template, create_call, temLin, rsrc,
+ add_random_after_barrier, yes_set_barrier );
+ if (policy_info.exportable) {
+ policy_info.usage_string.assign ("PSA_KEY_USAGE_EXPORT");
+ define_call<add_policy_usage_call> (set_data, random_data,
+ fill_in_template, create_call, temLin, rsrc,
+ add_to_end_bool, dont_set_barrier );
+ }
+ if (policy_info.copyable) {
+ policy_info.usage_string.assign ("PSA_KEY_USAGE_COPY");
+ define_call<add_policy_usage_call> (set_data, random_data,
+ fill_in_template, create_call, temLin, rsrc,
+ add_to_end_bool, dont_set_barrier );
+ }
+ if (policy_info.can_encrypt) {
+ policy_info.usage_string.assign ("PSA_KEY_USAGE_ENCRYPT");
+ define_call<add_policy_usage_call> (set_data, random_data,
+ fill_in_template, create_call, temLin, rsrc,
+ add_to_end_bool, dont_set_barrier );
+ }
+ if (policy_info.can_decrypt) {
+ policy_info.usage_string.assign ("PSA_KEY_USAGE_DECRYPT");
+ define_call<add_policy_usage_call> (set_data, random_data,
+ fill_in_template, create_call, temLin, rsrc,
+ add_to_end_bool, dont_set_barrier );
+ }
+ if (policy_info.can_sign) {
+ policy_info.usage_string.assign ("PSA_KEY_USAGE_SIGN");
+ define_call<add_policy_usage_call> (set_data, random_data,
+ fill_in_template, create_call, temLin, rsrc,
+ add_to_end_bool, dont_set_barrier );
+ }
+ if (policy_info.can_verify) {
+ policy_info.usage_string.assign ("PSA_KEY_USAGE_VERIFY");
+ define_call<add_policy_usage_call> (set_data, random_data,
+ fill_in_template, create_call, temLin, rsrc,
+ add_to_end_bool, dont_set_barrier );
+ }
+ if (policy_info.derivable) {
+ policy_info.usage_string.assign ("PSA_KEY_USAGE_DERIVE");
+ define_call<add_policy_usage_call> (set_data, random_data,
+ fill_in_template, create_call, temLin, rsrc,
+ add_to_end_bool, dont_set_barrier );
+ }
+ define_call<set_policy_lifetime_call> (set_data, random_data,
+ fill_in_template, create_call, temLin, rsrc,
+ add_to_end_bool, dont_set_barrier );
+ define_call<set_policy_algorithm_call> (set_data, random_data,
+ fill_in_template, create_call, temLin, rsrc,
+ add_to_end_bool, dont_set_barrier );
+ define_call<set_policy_type_call> (set_data, random_data,
+ fill_in_template, create_call, temLin, rsrc,
+ add_to_end, yes_set_barrier );
+ define_call<set_policy_size_call> (set_data, random_data,
+ fill_in_template, create_call, temLin, rsrc,
+ add_to_end, yes_set_barrier );
+ }
+ 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:
+ 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) {
+ /* If the name of the primary asset is known, then add calls at
+ random, otherwise append to end. If not, then we do not know
+ what asset-name barrier to search for. */
+ bool add_to_end_bool = (random_asset != psa_asset_usage::all);
+
+ if (policy_info.get_policy_from_key) {
+ define_call<get_key_policy_call> (set_data, random_data,
+ fill_in_template, create_call, temLin, rsrc,
+ add_to_end_bool, yes_set_barrier );
+ }
+ define_call<get_policy_usage_call> (set_data, random_data,
+ fill_in_template, create_call, temLin, rsrc,
+ add_to_end_bool, yes_set_barrier );
+ define_call<get_policy_lifetime_call> (set_data, random_data,
+ fill_in_template, create_call, temLin, rsrc,
+ add_to_end_bool, dont_set_barrier );
+ define_call<get_policy_algorithm_call> (set_data, random_data,
+ fill_in_template, create_call, temLin, rsrc,
+ add_to_end_bool, dont_set_barrier );
+ define_call<get_policy_type_call> (set_data, random_data,
+ fill_in_template, create_call, temLin, rsrc,
+ add_to_end_bool, dont_set_barrier );
+ define_call<get_policy_size_call> (set_data, random_data,
+ fill_in_template, create_call, temLin, rsrc,
+ add_to_end_bool, dont_set_barrier );
+ if (print_data) {
+ /* Printing data, so we need to read and filter usage for various
+ attributes, one by one: */
+ policy_info.print_usage_true_string.assign ("key can be exported.");
+ policy_info.print_usage_false_string.assign ("key cannot be exported.");
+ policy_info.usage_string.assign ("PSA_KEY_USAGE_EXPORT");
+ define_call<print_policy_usage_call> (set_data, random_data,
+ fill_in_template, create_call, temLin, rsrc,
+ add_to_end, dont_set_barrier );
+ policy_info.print_usage_true_string.assign ("key can be copied.");
+ policy_info.print_usage_false_string.assign ("key cannot be copied.");
+ policy_info.usage_string.assign ("PSA_KEY_USAGE_COPY");
+ define_call<print_policy_usage_call> (set_data, random_data,
+ fill_in_template, create_call, temLin, rsrc,
+ add_to_end, dont_set_barrier );
+ policy_info.print_usage_true_string.assign ("key works for encryption.");
+ policy_info.print_usage_false_string.assign ("key is not for encryption.");
+ policy_info.usage_string.assign ("PSA_KEY_USAGE_ENCRYPT");
+ define_call<print_policy_usage_call> (set_data, random_data,
+ fill_in_template, create_call, temLin, rsrc,
+ add_to_end, dont_set_barrier );
+ policy_info.print_usage_true_string.assign ("key works for decyption.");
+ policy_info.print_usage_false_string.assign ("key is not for decyption.");
+ policy_info.usage_string.assign ("PSA_KEY_USAGE_DECRYPT");
+ define_call<print_policy_usage_call> (set_data, random_data,
+ fill_in_template, create_call, temLin, rsrc,
+ add_to_end, dont_set_barrier );
+ policy_info.print_usage_true_string.assign ("key works for signing.");
+ policy_info.print_usage_false_string.assign ("key is not for signing.");
+ policy_info.usage_string.assign ("PSA_KEY_USAGE_SIGN");
+ define_call<print_policy_usage_call> (set_data, random_data,
+ fill_in_template, create_call, temLin, rsrc,
+ add_to_end, dont_set_barrier );
+ policy_info.print_usage_true_string.assign ("key can be used to verify.");
+ policy_info.print_usage_false_string.assign ("key not for verify.");
+ policy_info.usage_string.assign ("PSA_KEY_USAGE_VERIFY");
+ define_call<print_policy_usage_call> (set_data, random_data,
+ fill_in_template, create_call, temLin, rsrc,
+ add_to_end, dont_set_barrier );
+ policy_info.print_usage_true_string.assign ("key can derive other keys.");
+ policy_info.print_usage_false_string.assign ("key cannot derive other keys.");
+ policy_info.usage_string.assign ("PSA_KEY_USAGE_DERIVE");
+ define_call<print_policy_usage_call> (set_data, random_data,
+ fill_in_template, create_call, temLin, rsrc,
+ add_to_end, yes_set_barrier );
+ }
+ }
+ 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:
+ 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) {
+ if (policy_info.copy_key) {
+ // Copying a key:
+ define_call<copy_key_call> (set_info, random_data,
+ fill_in_template, create_call, temLin, rsrc,
+ add_to_end, yes_set_barrier);
+ } else if (set_data.string_specified || set_data.random_data) {
+ // Key data (key material) supplied:
+ define_call<create_key_call> (set_info, random_data,
+ fill_in_template, create_call, temLin, rsrc,
+ add_to_end, yes_set_barrier);
+ } else {
+ // Generate from scratch:
+ define_call<generate_key_call> (set_info, random_data,
+ fill_in_template, create_call, temLin, rsrc,
+ add_to_end, yes_set_barrier);
+ }
+ }
+ set_key_template_line (tf_fuzz_info *resources); // (constructor)
+ ~set_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:
+ 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<read_key_data_call> (set_data, random_data,
+ fill_in_template, create_call, temLin, rsrc,
+ add_to_end, yes_set_barrier);
+ }
+ read_key_template_line (tf_fuzz_info *resources); // (constructor)
+ ~read_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:
+ 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<remove_key_call> (set_data, random_data,
+ fill_in_template, create_call, temLin, rsrc,
+ add_to_end, yes_set_barrier);
+ }
+ remove_key_template_line (tf_fuzz_info *resources); // (constructor)
+ ~remove_key_template_line (void);
+
+protected:
+ // Data members:
+ // Methods:
+
+private:
+ // Data members:
+ // Methods:
+};
+
+#endif // #ifndef CRYPTO_TEMPLATE_LINE_HPP
diff --git a/tf_fuzz/template/crypto_template_line.o b/tf_fuzz/template/crypto_template_line.o
new file mode 100644
index 0000000..42e8502
--- /dev/null
+++ b/tf_fuzz/template/crypto_template_line.o
Binary files differ
diff --git a/tf_fuzz/template/secure_template_line.cpp b/tf_fuzz/template/secure_template_line.cpp
new file mode 100644
index 0000000..73fbde3
--- /dev/null
+++ b/tf_fuzz/template/secure_template_line.cpp
@@ -0,0 +1,73 @@
+/*
+ * 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_call (psa_call *call)
+{
+ // Copy asset info to call object for creation code -- the entire vector:
+ for (auto as_name : asset_info.asset_name_vector) {
+ /* Also copy into template line object's local vector: */
+ call->asset_info.asset_name_vector.push_back (as_name);
+ }
+ call->asset_info.id_n = asset_info.id_n;
+ // this call is currently limited to name-based
+ call->asset_info.name_specified = true;
+ call->asset_info.asset_ser_no = asset_info.asset_ser_no; // TODO: Does this make sense?
+ call->asset_info.how_asset_found = asset_search::found_active;
+ call->random_asset = random_asset;
+ call->set_data.string_specified = false; // shouldn't matter, but...
+ call->set_data.file_specified = false;
+ call->set_data.file_path.assign("");
+ call->set_data.set("");
+ call->set_data.flags_string.assign ("");
+ call->exp_data.pf_info_incomplete = true;
+ return true;
+}
+
+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/tf_fuzz/template/secure_template_line.hpp b/tf_fuzz/template/secure_template_line.hpp
new file mode 100644
index 0000000..7f53c70
--- /dev/null
+++ b/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 test template. Although these objects do largely
+ 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,
+ add_to_end, yes_set_barrier);
+ }
+ bool copy_template_to_call (psa_call *the_call);
+ 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/tf_fuzz/template/secure_template_line.o b/tf_fuzz/template/secure_template_line.o
new file mode 100644
index 0000000..bec2487
--- /dev/null
+++ b/tf_fuzz/template/secure_template_line.o
Binary files differ
diff --git a/tf_fuzz/template/sst_template_line.cpp b/tf_fuzz/template/sst_template_line.cpp
new file mode 100644
index 0000000..829071a
--- /dev/null
+++ b/tf_fuzz/template/sst_template_line.cpp
@@ -0,0 +1,110 @@
+/*
+ * 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"
+
+
+/**********************************************************************************
+ Methods of class set_sst_template_line follow:
+**********************************************************************************/
+
+//**************** set_sst_template_line methods ****************
+
+set_sst_template_line::set_sst_template_line (tf_fuzz_info *resources)
+ : sst_template_line (resources) // constructor)
+{
+ return; // just to have something to pin a breakpoint onto
+}
+
+
+// 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 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
+}
+
+// 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.
+**********************************************************************************/
+
+
+/**********************************************************************************
+ 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
+}
+
+// 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.
+**********************************************************************************/
+
diff --git a/tf_fuzz/template/sst_template_line.hpp b/tf_fuzz/template/sst_template_line.hpp
new file mode 100644
index 0000000..bec927c
--- /dev/null
+++ b/tf_fuzz/template/sst_template_line.hpp
@@ -0,0 +1,97 @@
+/*
+ * 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:
+ 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, add_to_end,
+ dont_set_barrier);
+ }
+ 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:
+ 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, add_to_end,
+ dont_set_barrier);
+ }
+ 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:
+ 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, add_to_end,
+ dont_set_barrier);
+ }
+ 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/tf_fuzz/template/sst_template_line.o b/tf_fuzz/template/sst_template_line.o
new file mode 100644
index 0000000..2be4f31
--- /dev/null
+++ b/tf_fuzz/template/sst_template_line.o
Binary files differ
diff --git a/tf_fuzz/template/template_line.cpp b/tf_fuzz/template/template_line.cpp
new file mode 100644
index 0000000..a8625b1
--- /dev/null
+++ b/tf_fuzz/template/template_line.cpp
@@ -0,0 +1,278 @@
+/*
+ * 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 test-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. */
+
+#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;
+ set_data.flags_string.assign ("");
+ random_asset = psa_asset_usage::all;
+ // if not deleting a random asset of a certain type, then search all as usual
+ target_barrier = "";
+ set_data.file_specified = false;
+ print_data = hash_data = false;
+ call_ser_no = -1;
+ asset_2_name.assign (""); asset_3_name.assign ("");
+ 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_info.asset_name_vector.erase (asset_info.asset_name_vector.begin(),
+ asset_info.asset_name_vector.end());
+ asset_info.asset_id_n_vector.erase (asset_info.asset_id_n_vector.begin(),
+ asset_info.asset_id_n_vector.end());
+}
+
+// (Default constructor not used)
+
+/**********************************************************************************
+ End of methods of class template_line.
+**********************************************************************************/
+
+
+/**********************************************************************************
+ Methods of class sst_template_line follow:
+**********************************************************************************/
+
+// (Currently, no need to specialize copy_template_to_call() for individual SST ops.)
+bool sst_template_line::copy_template_to_call (psa_call *call)
+{
+ // Copy asset info to call object for creation code:
+ call->asset_info = asset_info;
+ call->set_data = set_data;
+ call->set_data.string_specified = set_data.string_specified
+ || set_data.random_data;
+ // not really right, but more convenient to combine these two cases
+ call->assign_data_var_specified = assign_data_var_specified;
+ call->assign_data_var = assign_data_var;
+ call->random_asset = random_asset;
+ if (target_barrier == "") { // barriers are probably not used for SST, but...
+ call->target_barrier = asset_info.get_name();
+ } else {
+ call->target_barrier = target_barrier;
+ }
+ call->set_data.flags_string.assign (set_data.flags_string);
+ call->exp_data = expect;
+ call->exp_data.pf_info_incomplete = true;
+ call->id_string = asset_name; // data = expected
+ call->print_data = print_data;
+ call->hash_data = hash_data;
+ return true;
+}
+
+sst_template_line::sst_template_line (tf_fuzz_info *resources)
+ : template_line (resources)
+{
+ asset_info.asset_type = psa_asset_type::sst;
+}
+
+// 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)
+{
+ asset_info.asset_type = psa_asset_type::key;
+}
+
+bool key_template_line::copy_template_to_call (psa_call *call)
+{
+ // Copy asset info to call object for creation code:
+ call->asset_info = asset_info;
+ call->set_data = set_data;
+ call->set_data = set_data;
+ call->policy = policy_info;
+ call->asset_2_name = asset_2_name;
+ call->asset_3_name = asset_3_name;
+ call->set_data.string_specified = set_data.string_specified
+ || set_data.random_data;
+ // not really right, but more convenient to combine these two cases
+ call->assign_data_var_specified = assign_data_var_specified;
+ call->assign_data_var = assign_data_var;
+ call->random_asset = random_asset;
+ if (target_barrier == "") { // barriers are probably not used for SST, but...
+ call->target_barrier = asset_info.get_name();
+ } else {
+ call->target_barrier = target_barrier;
+ }
+ call->set_data.flags_string.assign (set_data.flags_string);
+ call->exp_data = expect;
+ call->exp_data.pf_info_incomplete = true;
+ call->id_string = asset_name; // data = expected
+ call->print_data = print_data;
+ call->hash_data = hash_data;
+ return true;
+}
+
+// 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_info.asset_type = psa_asset_type::policy;
+}
+
+bool policy_template_line::copy_template_to_call (psa_call *call)
+{
+ // Copy asset info to call object for creation code:
+ call->asset_info = asset_info;
+ call->set_data = set_data;
+ call->set_data = set_data;
+ call->policy = policy_info;
+ call->asset_2_name = asset_2_name;
+ call->asset_3_name = asset_3_name;
+ call->set_data.string_specified = set_data.string_specified
+ || set_data.random_data;
+ // not really right, but more convenient to combine these two cases
+ call->assign_data_var_specified = assign_data_var_specified;
+ call->assign_data_var = assign_data_var;
+ call->random_asset = random_asset;
+ if (target_barrier == "") { // barriers are probably not used for SST, but...
+ call->target_barrier = asset_info.get_name();
+ } else {
+ call->target_barrier = target_barrier;
+ }
+ call->set_data.flags_string.assign (set_data.flags_string);
+ call->exp_data = expect;
+ call->exp_data.pf_info_incomplete = true;
+ call->id_string = asset_name; // data = expected
+ call->print_data = print_data;
+ call->hash_data = hash_data;
+ return true;
+}
+
+// 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/tf_fuzz/template/template_line.hpp b/tf_fuzz/template/template_line.hpp
new file mode 100644
index 0000000..143232d
--- /dev/null
+++ b/tf_fuzz/template/template_line.hpp
@@ -0,0 +1,174 @@
+/*
+ * 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 test-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. */
+ expect_info expect; // everything about expected results
+ set_data_info set_data; // everything about setting PSA-asset data
+ asset_name_id_info asset_info; // everything about the asset(s) for this line
+ string asset_2_name; // if there's a 2nd asset, then this is its name
+ string asset_3_name; // if there's a 3rd asset, then this is its name
+ string target_barrier;
+ /* asset to tell the psa_call objects to set and search barrier to when
+ re-ordering PSA calls. For key policies, this is not necessarily the
+ nominal asset of that call. For a policy call, it is that policy asset,
+ so that later re-settings of the same policy don't pollute the current
+ setting of that policy. However, for key sets and reads, it is not the
+ key asset, but its policy. */
+ key_policy_info policy_info; // specific to crypto, but must be in base class
+ long call_ser_no; // unique identifer for psa_call tracker object
+ 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. */
+ bool assign_data_var_specified; // asset data to or from a named variable
+ 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_call (psa_call *the_call) = 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
+ // 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:
+ bool copy_template_to_call (psa_call *the_call);
+ 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:
+ // Methods:
+ bool copy_template_to_call (psa_call *the_call);
+ 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:
+ // Methods:
+ bool copy_template_to_call (psa_call *the_call);
+ 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/tf_fuzz/template/template_line.o b/tf_fuzz/template/template_line.o
new file mode 100644
index 0000000..ccdf59d
--- /dev/null
+++ b/tf_fuzz/template/template_line.o
Binary files differ
diff --git a/tf_fuzz/tests/example_template b/tf_fuzz/tests/example_template
new file mode 100644
index 0000000..4ecfd53
--- /dev/null
+++ b/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/tf_fuzz/tests/sstReads b/tf_fuzz/tests/sstReads
new file mode 100644
index 0000000..d2ad8b9
--- /dev/null
+++ b/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/tf_fuzz/tests/sstSets b/tf_fuzz/tests/sstSets
new file mode 100644
index 0000000..fb0981d
--- /dev/null
+++ b/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/tf_fuzz/tf_fuzz.cpp b/tf_fuzz/tf_fuzz.cpp
new file mode 100644
index 0000000..57ae836
--- /dev/null
+++ b/tf_fuzz/tf_fuzz.cpp
@@ -0,0 +1,512 @@
+/*
+ * 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"
+#include "variables.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 // 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);
+ }
+}
+
+// Return an iterator to a variable, if it exists. If not return variable.end().
+vector<variable_info>::iterator tf_fuzz_info::find_var (string var_name)
+{
+ vector<variable_info>::iterator the_var;
+ if (variable.empty()) {
+ return variable.end();
+ }
+ for (the_var = variable.begin(); the_var < variable.end(); the_var++) {
+ if (the_var->name == var_name) {
+ break;
+ }
+ }
+ return the_var;
+}
+// Add a variable to the vector if not already there; return true if already there.
+bool tf_fuzz_info::make_var (string var_name)
+{
+ bool found = false;
+ variable_info new_variable;
+
+ found = (find_var (var_name) != variable.end());
+ if (!found) {
+ new_variable.name.assign (var_name);
+ variable.push_back (new_variable);
+ }
+ return found;
+}
+
+
+// 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) {
+ // It turns out you're not allowed to remove "WRITE_ONCE" assets:
+ if ( asset->set_data.flags_string.find("PSA_STORAGE_FLAG_WRITE_ONCE")
+ == string::npos
+ ) {
+ call = bplate->bplate_string[teardown_sst];
+ find_replace_1st ("$uid", to_string(asset->asset_info.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 part of the preamble code:
+ work = bplate->bplate_string[preamble_B];
+ find_replace_all ("$purpose", test_purpose, work);
+ output_C_file << work;
+
+ output_C_file << " /* 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);
+ }
+
+ // Print out the final part of the preamble code:
+ work = bplate->bplate_string[preamble_C];
+ find_replace_all ("$purpose", test_purpose, work);
+ output_C_file << work;
+
+ output_C_file << "\n\n /* PSA calls to test: */" << endl;
+ for (auto call : calls) {
+ call->fill_in_command(); // (fills in check code too)
+ 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);
+}
+
+
+/* simulate_calls() goes through the vector of generated calls calculating expected
+ results for each. */
+void tf_fuzz_info::simulate_calls (void)
+{
+ bool asset_state_changed = false;
+
+ IV(cout << "Call sequence:" << endl;)
+ /* For now, much of the simulation "thinking" infrastructure is here for future
+ elaboration. The algorithm is to through each call one by one, copying
+ information to the asset in question. Then each currently-active asset is
+ allowed to react to that information until they all agree that they're
+ "quiescent." Finally, result information is copied from the asset back to
+ the call. */
+ for (auto this_call : calls) {
+ IV(cout << " " << this_call->call_description << " for asset "
+ << this_call->asset_info.get_name() << endl;)
+ this_call->copy_call_to_asset();
+ /* Note: this_call->the_asset will now point to the asset
+ associated with this_call, if any such asset exists. */
+ if (this_call->asset_info.the_asset != nullptr) {
+ /* If the asset exists, allow changes to it to affect other active
+ assets. */
+ asset_state_changed = false;
+ do {
+ for (auto this_asset : active_sst_asset) {
+ asset_state_changed |= this_asset->simulate();
+ }
+ for (auto this_asset : active_policy_asset) {
+ asset_state_changed |= this_asset->simulate();
+ }
+ for (auto this_asset : active_key_asset) {
+ asset_state_changed |= this_asset->simulate();
+ }
+ } while (asset_state_changed);
+ }
+ this_call->copy_asset_to_call();
+ }
+}
+
+
+/* Parse command-line parameters. exit() if error(s) found. Place results into
+ the 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);
+ }
+}
+
+
+void tf_fuzz_info::add_call (psa_call *the_call, bool append_bool,
+ bool set_barrier_bool) {
+ // For testing purposes only, uncomment this to force sequential ordering:
+ //append_bool = true;
+ vector<psa_call*>::size_type
+ barrier_pos = 0,
+ // barrier pos. before which calls for this asset may not be placed
+ insert_call_pos = 0, // where to place the new call
+ i; // loop index
+ bool barrier_found = false;
+ psa_call *candidate = nullptr; // (not for long)
+
+ if (set_barrier_bool) {
+ // Prevent calls regarding this asset being placed before this call:
+ the_call->barrier.assign (the_call->target_barrier);
+ IV(cout << "Inserted barrier for asset " << the_call->barrier << "." << endl;)
+ }
+ if (append_bool || calls.size() == 0) {
+ // Just .push_back() onto the end if asked to, or if this is the first call:
+ calls.push_back (the_call);
+ IV(cout << "Appended to end of call sequence: " << the_call->call_description
+ << "." << endl;)
+ return; // done, easy!
+ }
+ /* Now search for last call with a barrier for this asset. (Note: because
+ vector<psa_call*>::size_type is unsigned, we can't search backward from
+ .end(), decrementing past 0. Also, cannot initialize barrier_pos to -1;
+ must maintain boolean for that.) */
+ for (i = 0ULL, barrier_found = false; i < calls.size(); i++) {
+ candidate = calls[i];
+ if (candidate->barrier == the_call->target_barrier) {
+ barrier_pos = i;
+ barrier_found = true;
+ }
+ }
+ if (!barrier_found) {
+ /* STL-vector inserts occur *before* the stated index. With no barrier
+ found, we want to insert somewhere between before .begin() and after
+ .end(). So, we want a number between 0 and calls.size(), inclusive. */
+ insert_call_pos = (rand() % (calls.size() + 1));
+ IV(cout << "No barrier for asset " << the_call->asset_info.get_name()
+ << " found." << endl
+ << " Placing " << the_call->call_description
+ << " at position " << insert_call_pos << " in call sequence."
+ << endl;)
+ } else {
+ /* Insert at a random point between just after barrier and after the end
+ (including possibly after the end, but strictly after that barrier).
+ Since STL-vector inserts occur before the stated index, we want an
+ insertion point between the call after the barrier and calls.end(),
+ inclusive. */
+ insert_call_pos = (vector<psa_call*>::size_type)
+ ( barrier_pos + 1 // must be *after* barrier-carrying call
+ + (rand() % (calls.size() - barrier_pos))
+ );
+ IV(cout << "Barrier for asset " << the_call->asset_info.get_name()
+ << " found at position " << dec << barrier_pos << "." << endl;)
+ }
+ if (insert_call_pos == calls.size()) {
+ // Insert at end:
+ calls.push_back (the_call);
+ IV(cout << "Insertion position is at end of call list." << endl;)
+ } else {
+ // Insert before insert_call_position:
+ calls.insert (calls.begin() + insert_call_pos, the_call);
+ IV(cout << "Inserting " << the_call->call_description
+ << " at position " << dec << insert_call_pos << " in call sequence."
+ << endl;)
+ }
+}
+
+
+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 << "Call sequence generated." << endl;
+
+ cout << "Simulating call sequence..." << endl;
+ rsrc->simulate_calls();
+
+ 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/tf_fuzz/tf_fuzz.hpp b/tf_fuzz/tf_fuzz.hpp
new file mode 100644
index 0000000..ce9051f
--- /dev/null
+++ b/tf_fuzz/tf_fuzz.hpp
@@ -0,0 +1,202 @@
+/*
+ * 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"
+*/
+
+/* Shortcuts, to reduce code clutter, and reduce risk of coding errors. */
+#define IVM(content) if(rsrc->verbose_mode){content} // IVM = "If Verbose Mode"
+#define IV(content) if(verbose_mode){content} // Same, but for use by tf_fuzz methods
+
+
+// consts to help readability:
+const bool add_to_end = true; // add a call to the end of the call vector
+const bool add_random_after_barrier = false;
+ /* add to the call list randomly after the latest barrier for this asset, and
+ as late as the end of the list. */
+const bool yes_set_barrier = true; // create the call and set a barrier for that asset
+const bool dont_set_barrier = false;
+ // inserted call does not preclude calls related to that asset being placed earlier
+
+using namespace std;
+
+// class tf_fuzz_info mostly just groups together everything needed generate the test.
+class tf_fuzz_info
+{
+ /* In creating a test, TF-Fuzz parses the test template, creating a vector of
+ PSA-call-tracker objects. TF-Fuzz then performs a simulation of those calls
+ -- simulation only in enough detail to predict expected results of those PSA
+ calls. After that simulation phase, write_test() writes it all out. The
+ process of creating these structures also requires the boilerplate text
+ strings. */
+
+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
+ /* The "variable" vector tracks variables in the generated code. Actually,
+ it tracks variables explicitly named in the test template, and actual-data
+ holder variables from reading an asset. It does not track asset set-data
+ or asset expect-data variables, because there are multiple versions of
+ those, and it's easier to just to "count off" those multiple versions.
+ Notice that, unlike the above vectors, the variable vector is not a
+ vector of pointers to variable_info objects, but of the objects themselves.
+ This is because polymorphism is not of concern here. */
+ vector<variable_info> variable;
+ string test_purpose; // what the test tests
+ 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, // 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
+ );
+ vector<variable_info>::iterator find_var (string var_name);
+ void parse_cmd_line_params (int argc, char* argv[]);
+ // parse command-line parameters, and open files
+ void add_call (psa_call *the_call, bool to_end, bool set_barrier_bool);
+ /* stuffs a new call into the call list, either sequentially or at a random
+ place after a "barrier" for that particular asset. If set_barrier_bool
+ is true, it will prevent calls related to this asset from going before
+ this call. */
+ bool make_var (string var_name);
+ void simulate_calls (void);
+ // goes through generated calls calculating expected results
+ void write_test (void); // writes out the test's .c file
+ void teardown_test(void); // removes any PSA resources used in the test
+ 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,
+ bool to_end_bool, bool set_barrier_bool) {
+ 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 = 12 + (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) {
+ the_call = new CALL_TYPE (rsrc, temLin->call_ser_no,
+ temLin->asset_info.how_asset_found);
+ if (!temLin->copy_template_to_call (the_call)) {
+ cerr << "Error: Tool-internal: Please report error "
+ << "#402 to the TF-Fuzz developers." << endl;
+ exit(402);
+ }
+ rsrc->add_call (the_call, to_end_bool, set_barrier_bool);
+ }
+}
+
+#endif // #ifndef TF_FUZZ_HPP
diff --git a/tf_fuzz/tf_fuzz.o b/tf_fuzz/tf_fuzz.o
new file mode 100644
index 0000000..0e33578
--- /dev/null
+++ b/tf_fuzz/tf_fuzz.o
Binary files differ
diff --git a/tf_fuzz/tfz b/tf_fuzz/tfz
new file mode 100755
index 0000000..7d588ca
--- /dev/null
+++ b/tf_fuzz/tfz
Binary files differ
diff --git a/tf_fuzz/utility/README b/tf_fuzz/utility/README
new file mode 100644
index 0000000..5285fff
--- /dev/null
+++ b/tf_fuzz/utility/README
@@ -0,0 +1,11 @@
+As its name implies, this .../tf_fuzz/utility directory just contains
+various utility-compute code.
+
+
+For more information, please browse to:
+
+ https://ci.trustedfirmware.org/job/tf-m-build-test-nightly/lastSuccessfulBuild/artifact/build-docs/tf-m_documents/install/doc/user_guide/html/docs/user_guides/tf_fuzz/utility_dir.html
+
+--------------
+
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
diff --git a/tf_fuzz/utility/compute.cpp b/tf_fuzz/utility/compute.cpp
new file mode 100644
index 0000000..708a1f3
--- /dev/null
+++ b/tf_fuzz/utility/compute.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <cstdint> // for uint32_t
+#include "compute.hpp"
+
+
+using namespace std;
+
+/**********************************************************************************
+ Methods of class crc32 follow:
+**********************************************************************************/
+
+crc32::crc32 (void)
+{
+ shift_reg = 0x55555555; // just give it some default value
+}
+
+void crc32::seed_lfsr (uint32_t init_value)
+{
+ shift_reg = init_value;
+}
+
+/* lfsr_1b() performs one shift of the LFSR, factoring in a single bit of info,
+ that single bit must be in the low-order bit of the parameter. It returns
+ the LFSR value, which may be ignored. */
+uint32_t crc32::lfsr_1b (uint32_t a_bit)
+{
+ bool odd;
+
+ odd = ((shift_reg ^ a_bit) & 1) == 1;
+ shift_reg >>= 1;
+ if (odd) {
+ shift_reg ^= polynomial;
+ }
+ if (shift_reg == 0) {
+ // Theoretically should never happen, but precaution...
+ seed_lfsr (0x55555555);
+ }
+ return shift_reg;
+}
+
+uint32_t crc32::crc (uint8_t a_byte)
+{
+ for (int i = 0; i < 8; i++) {
+ lfsr_1b ((uint32_t) a_byte);
+ a_byte >>= 1;
+ }
+ return shift_reg;
+}
+
+uint32_t crc32::crc (uint16_t a_halfword)
+{
+ for (int i = 0; i < 16; i++) {
+ lfsr_1b ((uint32_t) a_halfword);
+ a_halfword >>= 1;
+ }
+ return shift_reg;
+}
+
+uint32_t crc32::crc (uint32_t a_word)
+{
+ for (int i = 0; i < 32; i++) {
+ lfsr_1b ((uint32_t) a_word);
+ a_word >>= 1;
+ }
+ return shift_reg;
+}
+
+/**********************************************************************************
+ End of methods of class crc32.
+**********************************************************************************/
diff --git a/tf_fuzz/utility/compute.hpp b/tf_fuzz/utility/compute.hpp
new file mode 100644
index 0000000..c6ece6c
--- /dev/null
+++ b/tf_fuzz/utility/compute.hpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef COMPUTE_HPP
+#define COMPUTE_HPP
+
+#include <cstdlib>
+
+using namespace std;
+
+/* Arguably at least, this LFSR-based hashing code is run more commonly on the
+ target itself -- included in the generated code -- than it is run here.
+ However, it's available here too, such as to parallel-calculate expected hash
+ values. */
+
+class crc32
+{
+public:
+ void seed_lfsr (uint32_t init_value);
+ /* lfsr_1b() performs one shift of the LFSR, factoring in a single bit of info,
+ that single bit must be in the low-order bit of the parameter. */
+ uint32_t lfsr_1b (uint32_t a_bit);
+ // crc() has two overloadings, calculating the CRC for byte or word quantities:
+ uint32_t crc (uint8_t a_byte);
+ uint32_t crc (uint16_t a_halfword);
+ uint32_t crc (uint32_t a_word);
+ crc32 (void);
+private:
+ const uint32_t polynomial = 0xb4bcd35c;
+ uint32_t shift_reg;
+};
+
+#endif /* COMPUTE_HPP */
diff --git a/tf_fuzz/utility/compute.o b/tf_fuzz/utility/compute.o
new file mode 100644
index 0000000..ee4e580
--- /dev/null
+++ b/tf_fuzz/utility/compute.o
Binary files differ
diff --git a/tf_fuzz/utility/data_blocks.cpp b/tf_fuzz/utility/data_blocks.cpp
new file mode 100644
index 0000000..09a25e9
--- /dev/null
+++ b/tf_fuzz/utility/data_blocks.cpp
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/* These classes "cut down the clutter" by grouping together related data and
+ associated methods (most importantly their constructors) used in template_
+ line, psa_call, psa_asset (etc.). */
+
+#include <string>
+#include <vector>
+#include <cstdint>
+
+#include "class_forwards.hpp"
+
+#include "boilerplate.hpp"
+#include "randomization.hpp"
+#include "gibberish.hpp"
+#include "compute.hpp"
+#include "string_ops.hpp"
+#include "data_blocks.hpp"
+#include "psa_asset.hpp"
+#include "crypto_asset.hpp"
+#include "find_or_create_asset.hpp"
+#include "psa_call.hpp"
+#include "template_line.hpp"
+#include "tf_fuzz.hpp"
+
+
+
+/**********************************************************************************
+ Methods of class expect_info follow:
+**********************************************************************************/
+
+expect_info::expect_info (void) // (default constructor)
+{
+ pf_nothing = false; // by default, TF-Fuzz provides expected results
+ pf_pass = pf_fail = pf_specified = false;
+ pf_result_string.assign (""); data.assign ("");
+ data_var_specified = false;
+ data_var.assign (""); // name of expected-data variable
+ data_specified = false;
+ data_matches_asset = false;
+ data.assign ("");
+ pf_info_incomplete = true;
+ n_exp_vars = -1; // so the first reference is 0 (no suffix), then _1, _2, ...
+ expected_results_saved = false;
+}
+expect_info::~expect_info (void) // (destructor)
+{}
+
+void expect_info::set_pf_pass (void)
+{
+ pf_pass = true;
+ pf_fail = pf_nothing = pf_specified = false;
+ pf_result_string = "";
+}
+
+void expect_info::set_pf_fail (void)
+{
+ pf_fail = true;
+ pf_pass = pf_nothing = pf_specified = false;
+ pf_result_string = "";
+}
+
+void expect_info::set_pf_nothing (void)
+{
+ pf_nothing = true;
+ pf_fail = pf_pass = pf_specified = false;
+ pf_result_string = "";
+}
+
+void expect_info::set_pf_error (string error)
+{
+ pf_specified = true;
+ pf_result_string.assign (error); // just default "guess," to be filled in
+ pf_pass = pf_fail = pf_nothing = false;
+}
+
+/* The expected pass/fail results are not available from the parser until the call has
+ already been created. The flag, pf_info_incomplete, that indicates whether or not
+ the "expects" information has been filled in. If not, fill it in from the template,
+ once that info has been parsed. */
+void expect_info::copy_expect_to_call (psa_call *the_call)
+{
+ the_call->exp_data.pf_nothing = pf_nothing;
+ the_call->exp_data.pf_pass = pf_pass;
+ the_call->exp_data.pf_fail = pf_fail;
+ the_call->exp_data.pf_specified = pf_specified;
+ the_call->exp_data.pf_result_string = pf_result_string;
+ the_call->exp_data.expected_results_saved = true;
+ the_call->exp_data.pf_info_incomplete = false;
+}
+
+/**********************************************************************************
+ End of methods of class expect_info.
+**********************************************************************************/
+
+
+/**********************************************************************************
+ Class set_data_info methods regarding setting and getting asset-data values:
+**********************************************************************************/
+
+string set_data_info::rand_creation_flags (void)
+{
+ return ((rand() % 2) == 1)?
+ "PSA_STORAGE_FLAG_WRITE_ONCE" : "PSA_STORAGE_FLAG_NONE";
+
+ /* TODO: There are also PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION and
+ PSA_STORAGE_FLAG_NO_CONFIDENTIALITY, but they don't seem to appear
+ in any test suites, so it's iffy as to whether they really exist.
+ We'll not routinely initialize to them, for now at least, but if
+ we want to enable them, then uncomment the following:
+ string result = "";
+ const int most_flags = 2,
+ int n_flags = (rand() % most_flags);
+
+ for (int i = 0; i < ; i < n_flags; ++i) {
+ switch (rand() % 4) {
+ case 0:
+ result += "PSA_STORAGE_FLAG_NONE";
+ break;
+ case 1:
+ result += "PSA_STORAGE_FLAG_WRITE_ONCE";
+ break;
+ case 2:
+ result += "PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION";
+ break;
+ case 3:
+ result += "PSA_STORAGE_FLAG_NO_CONFIDENTIALITY";
+ break;
+ }
+ if (i < n_flags-1)
+ result += " | ";
+ }
+ if (result == "") result = "PSA_STORAGE_FLAG_NONE";
+*/
+}
+
+set_data_info::set_data_info (void) // (default constructor)
+{
+ literal_data_not_file = true; // currently, not using files as data sources
+ string_specified = false;
+ data.assign ("");
+ random_data = false;
+ file_specified = false;
+ file_path.assign ("");
+ n_set_vars = -1; // so the first reference is 0 (no suffix), then _1, _2, ...
+ data_offset = 0;
+ flags_string = rand_creation_flags();
+}
+set_data_info::~set_data_info (void) // (destructor)
+{}
+
+/* set() establishes:
+ * An asset's data value from a template line (e.g., set sst snort data "data
+ value"), and
+ * *That* such a value was directly specified, as opposed to no data value having
+ been specified, or a random data value being requested.
+ Arguably, this method "has side effects," in that it not only sets a value, but
+ also "takes notes" about where that value came from.
+*/
+void set_data_info::set (string set_val)
+{
+ literal_data_not_file = true; // currently, not using files as data sources
+ string_specified = true;
+ data.assign (set_val);
+}
+
+/* set_calculated() establishes:
+ * An asset's data value as *not* taken from a template line, and
+ * *That* such a value was not directly specified in any template line, such as
+ if a random data value being requested.
+ Arguably, this method "has side effects," in that it not only sets a value, but
+ also "takes notes" about where that value came from.
+*/
+void set_data_info::set_calculated (string set_val)
+{
+ literal_data_not_file = true; // currently, not using files as data sources
+ string_specified = false;
+ data.assign (set_val);
+}
+
+/* randomize() establishes:
+ * An asset's data value as *not* taken from a template line, and
+ * *That* such a value was randomized.
+ Arguably, this method "has side effects," in that it not only sets a value, but
+ also "takes notes" about where that value came from.
+*/
+void set_data_info::randomize (void)
+{
+ gibberish gib;
+ char gib_buff[4096]; // spew gibberish into here
+ int rand_data_length = 0;
+
+ string_specified = false;
+ random_data = true;
+ literal_data_not_file = true;
+ rand_data_length = 40 + (rand() % 256);
+ /* Note: Multiple assets do get different random data */
+ gib.sentence (gib_buff, gib_buff + rand_data_length - 1);
+ data = gib_buff;
+}
+
+/* Getter for protected member, data. Protected so that it can only be set by
+ set() or set_calculated(), above, to establish not only its value but
+ how it came about. */
+string set_data_info::get (void)
+{
+ return data;
+}
+
+/* Currently, files as data sources aren't used, so this whole method is not "of
+ use," but that might change at some point. */
+bool set_data_info::set_file (string file_name)
+{
+ literal_data_not_file = true;
+ string_specified = false;
+ data.assign ("");
+ file_specified = true;
+ // Remove the ' ' quotes around the file name:
+ file_name.erase (0, 1);
+ file_name.erase (file_name.length()-1, 1);
+ file_path = file_name;
+ return true;
+}
+
+/**********************************************************************************
+ End of methods of class set_data_info.
+**********************************************************************************/
+
+
+/**********************************************************************************
+ Class asset_name_id_info methods regarding setting and getting asset-data values:
+**********************************************************************************/
+
+asset_name_id_info::asset_name_id_info (void) // (default constructor)
+{
+ id_n_not_name = false; // (arbitrary)
+ id_n = 100LL + ((uint64_t) rand() % 10000); // default to random ID#
+ asset_name.assign ("");
+ id_n_specified = name_specified = false; // no ID info yet
+ asset_type = psa_asset_type::unknown;
+ how_asset_found = asset_search::not_found;
+ the_asset = nullptr;
+ asset_ser_no = -1;
+}
+asset_name_id_info::~asset_name_id_info (void)
+{
+ asset_name_vector.clear();
+ asset_id_n_vector.clear();
+}
+
+/* set_name() establishes:
+ * An asset's "human" name from a template line, and
+ * *That* that name was directly specified, as opposed to the asset being defined
+ by ID only, or a random name being requested.
+ Arguably, this method "has side effects," in that it not only sets a name, but
+ also "takes notes" about where that name came from.
+*/
+void asset_name_id_info::set_name (string set_val)
+{
+ /* Use this to set the name as specified in the template file. Call this only
+ if the template file does indeed define a name. */
+ name_specified = true;
+ asset_name.assign (set_val);
+}
+
+/* set_calc_name() establishes:
+ * An asset's "human" name *not* from a template line, and
+ * *That* that name was *not* directly specified in any template line.
+ Arguably, this method "has side effects," in that it not only sets a name, but
+ also "takes notes" about where that name came from.
+*/
+void asset_name_id_info::set_calc_name (string set_val)
+{
+ name_specified = false;
+ asset_name.assign (set_val);
+}
+
+// set_just_name() sets an asset's "human" name, without noting how that name came up.
+void asset_name_id_info::set_just_name (string set_val)
+{
+ asset_name.assign (set_val);
+}
+
+/* Getter for protected member, asset_name. Protected so that it can only be set by
+ set_name() or set_calc_name(), above, to establish not only its value but
+ how it came about. */
+string asset_name_id_info::get_name (void)
+{
+ return asset_name;
+}
+
+// Asset IDs can be set directly from a uint64_t or converted from a string:
+void asset_name_id_info::set_id_n (string set_val)
+{
+ id_n = stol (set_val, 0, 0);
+}
+void asset_name_id_info::set_id_n (uint64_t set_val)
+{
+ id_n = set_val;
+}
+
+// Create ID-based name:
+string asset_name_id_info::make_id_n_based_name (uint64_t id_n)
+{
+ string result;
+
+ switch (asset_type) {
+ case psa_asset_type::sst:
+ result = "SST_ID_";
+ break;
+ case psa_asset_type::key:
+ result = "Key_ID_";
+ break;
+ case psa_asset_type::policy:
+ result = "Policy_ID_";
+ break;
+ default:
+ cerr << "\nError: Tool-internal: Please report error "
+ << "#1223 to the TF-Fuzz developers." << endl;
+ exit(1223);
+ }
+ result.append(to_string(id_n));
+ return result;
+}
+
+/**********************************************************************************
+ End of methods of class asset_name_id_info.
+**********************************************************************************/
+
+
+/**********************************************************************************
+ Class key_policy_info methods:
+**********************************************************************************/
+
+key_policy_info::key_policy_info (void) // (default constructor)
+{
+ get_policy_from_key = false; // specify policy asset by a key that uses it.
+ copy_key = false; // not copying one key to another
+ /* The following settings are not necessarily being randomized in mutually-
+ consistent ways, for two reasons: First, the template should set all that
+ matter, and second, testing TF response to nonsensical settings is also
+ valuable. */
+ exportable = (rand()%2==1? true : false);
+ copyable = (rand()%2==1? true : false);
+ can_encrypt = (rand()%2==1? true : false);
+ can_decrypt = (rand()%2==1? true : false);
+ can_sign = (rand()%2==1? true : false);
+ can_verify = (rand()%2==1? true : false);
+ derivable = (rand()%2==1? true : false);
+ persistent = (rand()%2==1? true : false);
+ // There's a really huge number of possible key types; won't randomize all:
+ key_type = rand_key_type();
+ usage_string.assign ("");
+ print_usage_true_string.assign ("");
+ print_usage_false_string.assign ("");
+ key_algorithm = rand_key_algorithm();
+ n_bits = 55 + (rand() % 1000);
+ gibberish *gib = new gibberish;
+ char buffer[256];
+ char *end;
+ int buf_len = 5ULL + (uint64_t) (rand() % 10);
+ end = gib->word (false, buffer, buffer + buf_len);
+ *end = '\0';
+ buffer[buf_len] = '\0';
+ handle_str = buffer;
+ gib->sentence (buffer, buffer + (40ULL + (uint64_t) (rand() % 200)));
+ key_data = buffer;
+ delete gib;
+}
+key_policy_info::~key_policy_info (void) // (destructor)
+{
+ return; // (even if only to have something to pin a breakpoint on)
+}
+
+
+/**********************************************************************************
+ End of methods of class key_policy_info.
+**********************************************************************************/
diff --git a/tf_fuzz/utility/data_blocks.hpp b/tf_fuzz/utility/data_blocks.hpp
new file mode 100644
index 0000000..f4628a5
--- /dev/null
+++ b/tf_fuzz/utility/data_blocks.hpp
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <string>
+
+/* These classes "cut down the clutter" by grouping together related data and
+ associated methods (most importantly their constructors) used in template_
+ line, psa_call, psa_asset (etc.). */
+
+#ifndef DATA_BLOCKS_HPP
+#define DATA_BLOCKS_HPP
+
+/* This project's header files #including other project headers quickly becomes
+ unrealistically complicated. The only solution is for each .cpp to include
+ the headers it needs. However these in particular are mostly axiomatic: Not
+ dependent upon other classes. */
+
+
+using namespace std;
+
+
+/**********************************************************************************
+ Class expect_info is all about expected data and expected pass/fail information.
+ The members are therefore broken down with prefixes pf_ (for pass/fail) or
+ data_. Pass/fail, is broadly:
+ * "Pass" == the test passes
+ * "Specified" == some specified failure (e.g., no such asset)
+ * "Nothing" == no expectation
+ Expected data refers to psa-asset data values, generally after reading them.
+ Currently, they are limited to character strings, but that will probably be
+ generalized in the future.
+**********************************************************************************/
+
+class expect_info
+{
+public:
+ // Data members:
+ // Expected-result info:
+ bool pf_nothing; // true to not generate results-check(s)
+ bool pf_pass; // if !expect.pf_nothing, then pass is expected
+ bool pf_fail; // if "expect fail" was specified
+ bool pf_specified;
+ /* if !pf_nothing && !pf_pass, then
+ true == expected result was specified
+ false == tf_fuzz must model expected result, and
+ pf_result_string is the expected result */
+ string pf_result_string;
+ bool data_specified; // (literal expected data specified)
+ string data; // what test template expects data from reading an asset to be
+ int n_exp_vars; // how many check-value variables have been created
+ bool data_var_specified; // check against a variable
+ string data_var; // name of variable containing expected data
+ bool pf_info_incomplete;
+ /* In parsing the template, the expect information comes later than the
+ rest of the call info. This flag tells us to fill in the pass/fail
+ expect info when it comes available. */
+ bool expected_results_saved;
+ /* This indicates whether expected results have or have not already been
+ copied to this call. It's a "one-shot," so to speak, to copy only
+ once when results are known good. Since calls can be inserted into
+ earlier points in the call sequence (not always appended), the call
+ sequence has to be gone over for this process multiple times. */
+ // Methods:
+ expect_info (void); // (default constructor)
+ ~expect_info (void); // (destructor)
+ void set_pf_pass (void);
+ void set_pf_fail (void);
+ void set_pf_nothing (void);
+ void set_pf_error (string error);
+ void copy_expect_to_call (psa_call *the_call);
+
+protected:
+ // Data members:
+ bool data_matches_asset;
+ /* true if template specifies expected data, and that expected data
+ agrees with that in the asset */
+};
+
+
+/**********************************************************************************
+ Class set_data_info addresses PSA-asset data values as affected, directly or
+ indirctly/implicitly, by the template-line content. "Directly," that is, by
+ virtue of the template line stating verbatim what to set data to, or indirectly
+ by virtue of telling TF-Fuzz to create random data for it.
+**********************************************************************************/
+
+class set_data_info
+{
+public:
+ // Data members:
+ bool string_specified;
+ // true if a string of data is specified in template file
+ bool random_data; // true to generate random data for the asset
+ bool file_specified; // true if a file of expected data was specified
+ bool literal_data_not_file;
+ // true to use data strings rather than files as data source
+ int n_set_vars; // how many implicit set variables have been created
+ string file_path; // path to file, if specified
+ string flags_string;
+ // creation flags, nominally for SST but have to be in a vector of base-class
+ uint32_t data_offset; // offset into asset data
+ // Methods:
+ set_data_info (void); // (default constructor)
+ ~set_data_info (void); // (destructor)
+ void set (string set_val);
+ void set_calculated (string set_val);
+ void randomize (void);
+ string get (void);
+ bool set_file (string file_name);
+
+protected:
+ // Data members:
+ string data; // String describing asset data.
+ // Methods:
+ string rand_creation_flags (void);
+};
+
+
+/**********************************************************************************
+ Class asset_name_id_info groups together and acts upon all information related to the
+ human names (as reflected in the code variable names, etc.) for PSA assets.
+**********************************************************************************/
+
+class asset_name_id_info
+{
+public:
+ // Data members (not much value in "hiding" these behind getters)
+ psa_asset *the_asset;
+ psa_asset_type asset_type; // SST vs. key vs. policy (etc.)
+ bool id_n_not_name; // true to create a PSA asset by ID
+ bool name_specified; // true iff template supplied human name
+ bool id_n_specified; // true iff template supplied ID #
+ vector<string> asset_name_vector;
+ vector<int> asset_id_n_vector;
+ long asset_ser_no; // unique ID for psa asset needed to find data string
+ asset_search how_asset_found;
+ uint64_t id_n; // asset ID# (e.g., SST UID).
+ /* Note: This is just a holder to pass ID from template-line to call. The
+ IDs for a given template line are in asset_info.asset_id_n_vector. */
+ // Methods:
+ asset_name_id_info (void); // (default constructor)
+ ~asset_name_id_info (void); // (destructor)
+ void set_name (string set_val);
+ void set_calc_name (string set_val);
+ void set_just_name (string set_val);
+ string get_name (void);
+ void set_id_n (string set_val);
+ void set_id_n (uint64_t set_val);
+ string make_id_n_based_name (uint64_t id_n);
+ // create UID-based asset name
+
+protected:
+ // Data members:
+ string asset_name; // parsed from template, assigned to psa_asset object
+};
+
+
+/**********************************************************************************
+ Class key_policy_info collects together the aspects of a Crypto key attributes
+ ("policies"). These include aspects that can affect TF-Fuzz's test-generation.
+**********************************************************************************/
+
+class key_policy_info
+{
+public:
+ // Data members:
+ // Digested info:
+ bool get_policy_from_key;
+ /* if true, then we must get policy info from a stated key; the asset
+ here is a key that uses the policy, and not the policy itself. */
+ bool implicit_policy;
+ /* if true, then the key was defined with policy specifications, but not
+ a named policy, meaning that we have to create an implicit policy. */
+ bool copy_key; // true to indicate copying one key to another
+ bool exportable; // key data can be exported (viewed - fail exports if not).
+ bool copyable; // can be copied (fail key-copies if not).
+ bool can_encrypt; // OK for encryption (fail other uses).
+ bool can_decrypt; // OK for decryption (fail other uses).
+ bool can_sign; // OK for signing (fail other operations).
+ bool can_verify; // OK for verifing a message signature (fail other uses).
+ bool derivable; // OK for derive other keys (fail other uses).
+ bool persistent; // must be deleted at the end of test.
+ string usage_string;
+ /* This string is set to a PSA_KEY_USAGE_* value in the template
+ immediately prior to making define_call<add_policy_usage_call>.
+ The copy_template_to_call() therein sets the corresponding string
+ in the call, and that is copied into the code in the fill_in_command()
+ invocation. */
+ string print_usage_true_string;
+ /* For printing out policy usage, this states how to describe the usage
+ if it can be used this way. This is managed similarly with, and used
+ in conjunction with usage_string above. NOTE: THIS ALSO SERVES AS AN
+ INDICATOR WHETHER OR NOT TO PRINT ON A GET-USAGE CALL. "" means not
+ to print. */
+ string print_usage_false_string;
+ /* Also for printing out policy usage, this is how to describe usage if
+ it cannot be used this way. */
+ string key_type; // AES, DES, RSA pair, DS public, etc.
+ string key_algorithm;
+ int n_bits;
+ // for get_key_info call (possibly others) exected key size in bits
+ string handle_str; // the text name of the key's "handle"
+ string key_data; // the key data as best we can know it.
+ string asset_2_name;
+ // if there's a 2nd asset, such as policy on key call, this is its name
+ string asset_3_name; // if there's a 3rd asset, then this is its name
+
+ // Methods:
+ key_policy_info (void); // (default constructor)
+ ~key_policy_info (void); // (destructor)
+
+
+protected:
+ // Data members:
+ bool data_matches_asset;
+ /* true if template specifies expected data, and that expected data
+ agrees with that in the asset */
+};
+
+
+
+#endif // DATA_BLOCKS_HPP
+
diff --git a/tf_fuzz/utility/data_blocks.o b/tf_fuzz/utility/data_blocks.o
new file mode 100644
index 0000000..58a37a9
--- /dev/null
+++ b/tf_fuzz/utility/data_blocks.o
Binary files differ
diff --git a/tf_fuzz/utility/find_or_create_asset.hpp b/tf_fuzz/utility/find_or_create_asset.hpp
new file mode 100644
index 0000000..3daf37c
--- /dev/null
+++ b/tf_fuzz/utility/find_or_create_asset.hpp
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef FIND_OR_CREATE_ASSET_HPP
+#define FIND_OR_CREATE_ASSET_HPP
+
+using namespace std;
+
+/* This enum defines possible results when asked to find an existing, or create a
+ new PSA asset. */
+enum class asset_search
+{ found_active, // found as an actively-used asset
+ found_deleted, // found as a previously-used, but now-unusable asset
+ found_invalid, // found as a previously-used, but now-unusable asset
+ not_found, // if not found and if not allowed to create it
+ created_new, // no such existing asset was found so created new, active asset
+ unsuccessful, // ran out of memory or whatever
+ something_wrong // something wrong with the code; shouldn't happen
+};
+// Search areas:
+enum class psa_asset_usage // one particular area or all
+{ active, // found as an actively-used asset
+ deleted, // found as a previously-used, but now-unusable asset
+ invalid, // (invalid assets aren't completely defined yet)
+ all, // if not found and if not allowed to create it
+ none // just create it
+};
+// In searching for an asset, this enum specifies what to search for:
+enum class psa_asset_search
+{ name, // its human name
+ id, // its id, such as SST UID
+ serial // its serial number assigned upon creation
+};
+// Types of assets:
+enum class psa_asset_type
+{ sst, // (pretty obvious what each of these mean)
+ key,
+ policy,
+ unknown
+};
+
+
+// A few consts just to make code more readable:
+const bool yes_create_asset = true;
+const bool dont_create_asset = false;
+
+
+/* There are several variants, by asset type, of this method. So, C++ templating
+ is best. Note that, while the vectors are pointers to the base, psa_asset type,
+ the individual entries are all of the same ASSET_TYPE type. */
+template <typename ASSET_TYPE>
+asset_search generic_find_or_create_asset (
+ vector<psa_asset*> &active_asset_vector, // the three vectors of known assets
+ vector<psa_asset*> &deleted_asset_vector,
+ vector<psa_asset*> &invalid_asset_vector,
+ psa_asset_search criterion, // what to search on
+ psa_asset_usage where, // where to search
+ string target_name, // ignored if not searching on name
+ uint64_t target_id, // also ignored if not searching on ID (e.g., SST UID)
+ long &serial_no, // search on this if requested, but return serial regardless
+ bool create_asset, // true to create the asset if it doesn't exist
+ typename vector<psa_asset*>::iterator &asset
+ // returns iterator to the requested asset
+) {
+ ASSET_TYPE *new_asset;
+ bool match = false; // match found
+ // Look first in active assets:
+ if (where == psa_asset_usage::active || where == psa_asset_usage::all) {
+ for (auto as = active_asset_vector.begin(); as < active_asset_vector.end();
+ ++as) {
+ psa_asset *pass = *as;
+ switch (criterion) {
+ case psa_asset_search::name: // human-meaningful name
+ match = (pass->asset_info.get_name() == target_name);
+ break;
+ case psa_asset_search::id: // ID#
+ match = (pass->asset_info.id_n == target_id);
+ break;
+ default: // psa_asset_search::serial
+ match = (pass->asset_info.asset_ser_no == serial_no);
+ break;
+ }
+ if (match) {
+ asset = as;
+ return asset_search::found_active;
+ }
+ }
+ }
+ // Look then in deleted assets:
+ if (where == psa_asset_usage::deleted || where == psa_asset_usage::all) {
+ for (auto as = deleted_asset_vector.begin(); as < deleted_asset_vector.end();
+ ++as) {
+ psa_asset *pass = *as;
+ switch (criterion) {
+ case psa_asset_search::name: // human-meaningful name
+ match = (pass->asset_info.get_name() == target_name);
+ break;
+ case psa_asset_search::id: // ID#
+ match = (pass->asset_info.id_n == target_id);
+ break;
+ default: // psa_asset_search::serial
+ match = (pass->asset_info.asset_ser_no == serial_no);
+ break;
+ }
+ if (match) {
+ asset = as;
+ if (create_asset) {
+ /* Asset previously existed, but has since been removed. Resur-
+ rect it into active assets, but zap its data: */
+ pass->set_data.set("");
+ pass->exp_data.data.assign("");
+ deleted_asset_vector.erase (as);
+ active_asset_vector.push_back (pass);
+ return asset_search::found_active; // it's active now anyway...
+ } else {
+ return asset_search::found_deleted;
+ }
+ }
+ }
+ }
+ // Look then in invalid assets:
+ if (where == psa_asset_usage::invalid || where == psa_asset_usage::all) {
+ for (auto as = invalid_asset_vector.begin(); as < invalid_asset_vector.end();
+ ++as) {
+ psa_asset *pass = *as;
+ switch (criterion) {
+ case psa_asset_search::name: // human-meaningful name
+ match = (pass->asset_info.get_name() == target_name);
+ break;
+ case psa_asset_search::id: // ID#
+ match = (pass->asset_info.id_n == target_id);
+ break;
+ default: // psa_asset_search::serial
+ match = (pass->asset_info.asset_ser_no == serial_no);
+ break;
+ }
+ if (match) {
+ asset = as;
+ return asset_search::found_invalid;
+ }
+ }
+ }
+ // Couldn't find it in any of the existing lists, so create it in active assets:
+ if (create_asset) {
+ try {
+ new_asset = new ASSET_TYPE;
+ if (criterion == psa_asset_search::id) {
+ new_asset->asset_info.id_n = target_id;
+ } // TO DO: probably should do the same for its name in a name search!
+ active_asset_vector.push_back(new_asset);
+ asset = prev(active_asset_vector.end());
+ return asset_search::created_new;
+ }
+ catch (std::bad_alloc& bad) {
+ std::cerr << "Error: Failed to allocate an ASSET_TYPE: " << bad.what()
+ << endl;
+ return asset_search::unsuccessful;
+ }
+ } else {
+ return asset_search::not_found;
+ }
+ return asset_search::something_wrong; // should never get here
+}
+
+#endif // ifndef FIND_OR_CREATE_ASSET_HPP
diff --git a/tf_fuzz/utility/gibberish.cpp b/tf_fuzz/utility/gibberish.cpp
new file mode 100644
index 0000000..58a3f8f
--- /dev/null
+++ b/tf_fuzz/utility/gibberish.cpp
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/*
+ * These functions produce random-gibberish quasi-words in a quasi-sentence.
+ * Random character streams may be conceptually sufficient, but for testing
+ * purposes, it's much easier for humans to remember and to distinguish semi-
+ * pro-nounceable gibberish like "dokwab neltiegib..." than
+ * "f7H%r^&B*5|j6@Mz>\#...".
+ */
+
+#include <string>
+
+#include "gibberish.hpp" // shouldn't need any other project headers
+
+
+/**
+ * \brief Returns a letter for random-gibberish quasi-words in a quasi-sentence.
+ *
+ * \return A letter character value.
+ *
+ */
+char gibberish::letter(void)
+{
+ return 'a' + (rand() % ('z'-'a' + 1));
+}
+
+
+/**
+ * \brief Returns a vowel for random-gibberish quasi-words in a quasi-sentence.
+ *
+ * \return A vowel character value.
+ *
+ */
+char gibberish::vowel(void)
+{
+ char vowels[] = "aeiou";
+
+ return vowels[rand() % 5];
+}
+
+
+/**
+ * \brief Returns a consonant for random-gibberish quasi-words in a quasi-sentence.
+ *
+ * \return A consonant character value.
+ *
+ */
+char gibberish::consonant(void)
+{
+ char candidate;
+
+ do {
+ candidate = letter();
+ } while ( candidate == 'a' || candidate == 'e' || candidate == 'i'
+ || candidate == 'o' || candidate == 'u');
+ return candidate;
+}
+
+
+/**
+ * \brief Appends a semi-pronounceable syllable onto a string, stopping before
+ * the end of the string, for random-gibberish quasi-words in a
+ * quasi-sentence. Returns a pointer to the next open spot in the string.
+ *
+ * \param[in] string_ptr Pointer to where to put the word.
+ *
+ * \param[in] stop Pointer to last character in quasi-sentence.
+ *
+ * \return Pointer to first character after the word.
+ *
+ */
+char *gibberish::syllable (char *string_ptr, char *stop)
+{
+ char *parser; /* points into string while building it */
+
+ parser = string_ptr;
+ if ((rand() % 4) < 3) {
+ if (parser < stop) *parser++ = consonant();
+ if (parser < stop) *parser++ = vowel();
+ if (parser < stop) *parser++ = letter();
+ } else {
+ if (parser < stop) *parser++ = vowel();
+ if (((rand() % 4) < 1) && parser < stop) {
+ *parser++ = vowel();
+ }
+ if (parser < stop) *parser++ = consonant();
+ }
+ return parser;
+}
+
+
+/**
+ * \brief Appends a mostly-pronounceable quasi-word onto a quasi-sentence string,
+ * stopping before the end of the string. Returns a pointer to the next
+ * open spot in the string.
+ *
+ * \param[in] initial_cap: True if the first character should be capitalized.
+ *
+ * \param[in] string_ptr Pointer to where to put the word.
+ *
+ * \param[in] stop Pointer to last character in quasi-sentence.
+ *
+ * \return Pointer to first character after the word.
+ *
+ */
+char *gibberish::word (bool initial_cap, char *string_ptr, char *stop)
+{
+ int syllable_count;
+ char *parser; /* points into string while building it */
+ string avoid_check;
+ bool has_avoid_words;
+ do {
+ has_avoid_words = false;
+ for (syllable_count = 0, parser = string_ptr;
+ syllable_count < 4
+ && (rand() % 5) >= syllable_count
+ && parser < stop;
+ syllable_count++) {
+ parser = syllable (parser, stop);
+ }
+ for (int i = 0; i < n_avoids; i++) {
+ avoid_check = string_ptr;
+ if (avoid[i] == avoid_check) {
+ has_avoid_words = true;
+ break;
+ }
+ }
+ if (initial_cap) {
+ *string_ptr -= 'a' - 'A'; /* more or less assumes ASCII */
+ }
+ } while (has_avoid_words);
+ return parser;
+}
+
+
+/**
+ * \brief Creates a mostly-pronounceable, random-gibberish quasi-sentence,
+ * stopping before the end of the string.
+ *
+ * \param[in] string_ptr Pointer to beginning of string for quasi-sentence.
+ *
+ * \param[in] stop Pointer to last character in quasi-sentence.
+ *
+ */
+void gibberish::sentence (char *string_ptr, char *stop)
+{
+ char *parser; /* points into string while building it */
+ char punctuation[] = ".?!";
+
+ *stop = '\0'; /* null-terminate the string */
+ --stop;
+ parser = word (capitalize, string_ptr, stop);
+ if (parser < stop) {
+ *parser++ = ' ';
+ }
+ for (; parser < stop; ) {
+ parser = word (dont_capitalize, parser, stop);
+ if (parser < stop) {
+ *parser++ = ' ';
+ }
+ }
+ parser--;
+ if (*parser == ' ') {
+ *parser = vowel(); // just to not have a blank at the end
+ }
+ *stop = punctuation[rand() % 3];
+}
+
+
+/**
+ * \brief Chooses a gibberish-sentence length.
+ *
+ */
+int gibberish::pick_sentence_len (void)
+{
+ return min_literal_data_len + (rand() % literal_data_len_span);
+}
+
+
+/**
+ * \brief Constructor for gibberish object.
+ *
+ */
+gibberish::gibberish (void)
+{
+ string holder;
+
+ for (int i = 0; i < n_avoids; i++) {
+ holder = avoid[i];
+ for (long unsigned int j = 0; j < holder.length(); j++) {
+ holder[j] = holder[j] - 1;
+ }
+ avoid[i] = holder;
+ }
+}
+
+
+/**
+ * \brief Destructor for gibberish object.
+ *
+ */
+gibberish::~gibberish (void)
+{
+ // Nothing to tear down.
+}
diff --git a/tf_fuzz/utility/gibberish.hpp b/tf_fuzz/utility/gibberish.hpp
new file mode 100644
index 0000000..c5692e3
--- /dev/null
+++ b/tf_fuzz/utility/gibberish.hpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/*
+ * sec-regress.c&.h implement the Scripted-Call Application, and other functions
+ * for the security-regression testing feature.
+ *
+ */
+
+#ifndef GIBBERISH_HPP
+#define GIBBERISH_HPP
+
+#include <cstdlib>
+
+using namespace std;
+
+class gibberish
+{
+public: // not much value in hiding these behind getters and setters
+ // Data members:
+ static const int min_literal_data_len = 32, max_literal_data_len = 512,
+ literal_data_len_span = max_literal_data_len - min_literal_data_len;
+ // Methods:
+ gibberish (void); // (constructor)
+ ~gibberish (void);
+ char letter (void);
+ char vowel (void);
+ char consonant (void);
+ char *syllable (char *string_ptr, char *stop);
+ char *word (bool initial_cap, char *string_ptr, char *stop);
+ int pick_sentence_len (void);
+ void sentence (char *string_ptr, char *stop);
+
+protected:
+ // Data members:
+ // Methods:
+
+private:
+ // Data members:
+ static const int n_avoids = 42;
+ string avoid[n_avoids] = {"bvup", "epvcmf", "jou", "tusvdu", "dpotu", "gmpbu",
+ "tipsu", "votjhofe", "csfbl", "fmtf", "mpoh", "txjudi",
+ "gvdl", "dpoujovf", "gps", "wbhjob", "tjhofe", "dpdl",
+ "wpje", "dbtf", "tiju", "fovn", "qfojt", "sfhjtufs",
+ "qjtt", "uzqfefg", "efgbvmu", "ujut", "hpup", "tj{fpg",
+ "uxbu", "wpmbujmf", "dvou", "dibs", "fyufso", "sfuvso",
+ "dpjuvt", "vojpo", "ep", "jg", "tubujd", "xijmf"};
+ static const bool capitalize = true;
+ static const bool dont_capitalize = false;
+ // Parameters of random SST-asset generation:
+ // Methods:
+};
+
+#endif /* GIBBERISH_HPP */
diff --git a/tf_fuzz/utility/gibberish.o b/tf_fuzz/utility/gibberish.o
new file mode 100644
index 0000000..b5d4038
--- /dev/null
+++ b/tf_fuzz/utility/gibberish.o
Binary files differ
diff --git a/tf_fuzz/utility/randomization.cpp b/tf_fuzz/utility/randomization.cpp
new file mode 100644
index 0000000..23eb7d2
--- /dev/null
+++ b/tf_fuzz/utility/randomization.cpp
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/**********************************************************************************
+ Functions in this file are exactly that: functions, not methods of any class.
+ That is, they are stand-alone, utility functions linked in to the executable,
+ and available to whomever needs them.
+**********************************************************************************/
+
+#include "randomization.hpp"
+
+/**
+ * \brief Selects and returns a random key_usage_t value.
+ *
+ * \details
+ *
+ * \note
+ *
+ */
+string rand_key_usage (void)
+{
+ switch (rand() % 6) {
+ case 0: return "PSA_KEY_USAGE_EXPORT";
+ case 1: return "PSA_KEY_USAGE_ENCRYPT";
+ case 2: return "PSA_KEY_USAGE_DECRYPT";
+ case 3: return "PSA_KEY_USAGE_SIGN";
+ case 4: return "PSA_KEY_USAGE_VERIFY";
+ case 5: return "PSA_KEY_USAGE_DERIVE";
+ }
+ return ""; /* placate compiler */
+}
+
+/**
+ * \brief Selects and returns a random psa_algorithm_t value.
+ *
+ * \details
+ *
+ * \note
+ *
+ */
+/* TODO: Likely want to make additional versions of these specific for TLS,
+ asymmetric, symmetric... */
+string rand_key_algorithm (void)
+{
+ switch (rand() % 44) {
+ case 0: return "PSA_ALG_VENDOR_FLAG";
+ case 1: return "PSA_ALG_CATEGORY_MASK";
+ case 2: return "PSA_ALG_CATEGORY_HASH";
+ case 3: return "PSA_ALG_CATEGORY_MAC";
+ case 4: return "PSA_ALG_CATEGORY_CIPHER";
+ case 5: return "PSA_ALG_CATEGORY_AEAD";
+ case 6: return "PSA_ALG_CATEGORY_SIGN";
+ case 7: return "PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION";
+ case 8: return "PSA_ALG_CATEGORY_KEY_AGREEMENT";
+ case 9: return "PSA_ALG_CATEGORY_KEY_DERIVATION";
+ case 10: return "PSA_ALG_HASH_MASK";
+ case 11: return "PSA_ALG_MD2";
+ case 12: return "PSA_ALG_MD4";
+ case 13: return "PSA_ALG_MD5";
+ case 14: return "PSA_ALG_RIPEMD160";
+ case 15: return "PSA_ALG_SHA_1";
+ case 16: return "PSA_ALG_SHA_224";
+ case 17: return "PSA_ALG_SHA_256";
+ case 18: return "PSA_ALG_SHA_384";
+ case 19: return "PSA_ALG_SHA_512";
+ case 20: return "PSA_ALG_SHA_512_224";
+ case 21: return "PSA_ALG_SHA_512_256";
+ case 22: return "PSA_ALG_SHA3_224";
+ case 23: return "PSA_ALG_SHA3_256";
+ case 24: return "PSA_ALG_SHA3_384";
+ case 25: return "PSA_ALG_SHA3_512";
+ case 26: return "PSA_ALG_ANY_HASH";
+ case 27: return "PSA_ALG_MAC_SUBCATEGORY_MASK";
+ case 28: return "PSA_ALG_HMAC_BASE";
+ case 29: return "PSA_ALG_MAC_TRUNCATION_MASK";
+ case 30: return "PSA_ALG_CIPHER_MAC_BASE";
+ case 31: return "PSA_ALG_CBC_MAC";
+ case 32: return "PSA_ALG_CMAC";
+ case 33: return "PSA_ALG_CIPHER_STREAM_FLAG";
+ case 34: return "PSA_ALG_CIPHER_FROM_BLOCK_FLAG";
+ case 35: return "PSA_ALG_ARC4";
+ case 36: return "PSA_ALG_CTR";
+ case 37: return "PSA_ALG_CFB";
+ case 38: return "PSA_ALG_OFB";
+ case 39: return "PSA_ALG_XTS";
+ case 40: return "PSA_ALG_CBC_NO_PADDING";
+ case 41: return "PSA_ALG_CBC_PKCS7";
+ case 42: return "PSA_ALG_CCM";
+ case 43: return "PSA_ALG_GCM";
+ }
+ return ""; /* placate compiler */
+}
+
+
+/**
+ * \brief Selects and returns a random psa_key_type_t value.
+ *
+ * \details
+ *
+ * \note
+ *
+ */
+string rand_key_type (void)
+{
+ switch (rand() % 24) {
+ case 0: return "PSA_KEY_TYPE_NONE";
+ case 1: return "PSA_KEY_TYPE_VENDOR_FLAG";
+ case 2: return "PSA_KEY_TYPE_CATEGORY_MASK";
+ case 3: return "PSA_KEY_TYPE_CATEGORY_SYMMETRIC";
+ case 4: return "PSA_KEY_TYPE_CATEGORY_RAW";
+ case 5: return "PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY";
+ case 6: return "PSA_KEY_TYPE_CATEGORY_KEY_PAIR";
+ case 7: return "PSA_KEY_TYPE_CATEGORY_FLAG_PAIR";
+ case 8: return "PSA_KEY_TYPE_RAW_DATA";
+ case 9: return "PSA_KEY_TYPE_HMAC";
+ case 10: return "PSA_KEY_TYPE_DERIVE";
+ case 11: return "PSA_KEY_TYPE_AES";
+ case 12: return "PSA_KEY_TYPE_DES";
+ case 13: return "PSA_KEY_TYPE_CAMELLIA";
+ case 14: return "PSA_KEY_TYPE_ARC4";
+ case 15: return "PSA_KEY_TYPE_CHACHA20";
+ case 16: return "PSA_KEY_TYPE_RSA_PUBLIC_KEY";
+ case 17: return "PSA_KEY_TYPE_RSA_KEY_PAIR";
+ case 18: return "PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE";
+ case 19: return "PSA_KEY_TYPE_ECC_KEY_PAIR_BASE";
+ case 20: return "PSA_KEY_TYPE_ECC_CURVE_MASK";
+ case 21: return "PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE";
+ case 22: return "PSA_KEY_TYPE_DH_KEY_PAIR_BASE";
+ case 23: return "PSA_KEY_TYPE_DH_GROUP_MASK";
+ default: return "";
+ }
+ return ""; /* placate compiler */
+}
+
+
+
diff --git a/tf_fuzz/utility/randomization.hpp b/tf_fuzz/utility/randomization.hpp
new file mode 100644
index 0000000..2eb72f6
--- /dev/null
+++ b/tf_fuzz/utility/randomization.hpp
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef RANDOMIZATION_HPP
+#define RANDOMIZATION_HPP
+
+#include <string>
+
+using namespace std;
+
+string rand_key_usage (void);
+
+string rand_key_algorithm (void);
+
+string rand_key_type (void);
+
+#endif /* #ifndef RANDOMIZATION_HPP */
diff --git a/tf_fuzz/utility/randomization.o b/tf_fuzz/utility/randomization.o
new file mode 100644
index 0000000..1d19db9
--- /dev/null
+++ b/tf_fuzz/utility/randomization.o
Binary files differ
diff --git a/tf_fuzz/utility/string_ops.cpp b/tf_fuzz/utility/string_ops.cpp
new file mode 100644
index 0000000..9c14140
--- /dev/null
+++ b/tf_fuzz/utility/string_ops.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "string_ops.hpp"
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+
+using namespace std;
+
+// Replace first occurrence of find_str within orig of replace_str:
+size_t find_replace_1st (const string &find_str, const string &replace_str,
+ string &orig) {
+ size_t where = 0;
+ where = orig.find(find_str, where);
+ if (where != string::npos) {
+ orig.replace(where, find_str.length(), replace_str);
+ }
+ return where;
+}
+
+// Replace all occurrences of find_str in "this" string, with replace_str:
+size_t find_replace_all (const string &find_str, const string &replace_str,
+ string &orig) {
+ size_t where = 0;
+ do {
+ where = orig.find(find_str, where);
+ if (where != string::npos) {
+ orig.replace(where, find_str.length(), replace_str);
+ }
+ } while (where != string::npos);
+ return where;
+}
+
+
+string formalize (string input, string prefix) {
+ // First capitalize the input string:
+ for (auto cp = input.begin(); cp < input.end(); cp++) {
+ *cp = (char) toupper (*cp);
+ }
+ // If it already begins with the prefix...
+ if (input.substr (0, prefix.length()) == prefix) {
+ // then return it as capitalized:
+ return input;
+ } else {
+ // If not, prefix it with that prefix:
+ return prefix + input;
+ }
+}
+
+/* This implementation assumes ASCII character encoding and no "special characters" --
+ loosely speaking, "English." */
+string string_or_hex (string input, int clump_size) {
+ uint32_t n_alphanum = 0; // the number of alphanumeric characters
+ bool prose = true; // the string is alphanumeric, space, or common punctuation
+ ostringstream hex_stream;
+
+ for (auto cp = input.begin(); cp < input.end(); cp++) {
+ if ((int) *cp < 0) {
+ prose = false;
+ break;
+ }
+ if ( (*cp >= '0' && *cp <= '9')
+ || (*cp >= 'a' && *cp <= 'z') || (*cp >= 'A' && *cp <= 'Z')
+ || (*cp == ' ') || (*cp == ',') || (*cp == '.')
+ || (*cp == '?') || (*cp == '!')
+ ) {
+ n_alphanum++;
+ }
+ }
+ if ( prose // so far at least!
+ && ( (input.length() - n_alphanum) // number of chars that are not "English"
+ < (input.length() >> 3) // 1/8 of the length of the string
+ ) ) {
+ return input; // take it at face-value
+ }
+ // It's not run-of-the-mill text, so create a hex string:
+ int i = 0;
+ for (auto cp = input.begin(); cp < input.end(); cp++) {
+ hex_stream << setfill('0') << setw(2) << hex << (((unsigned) *cp) & 0xff);
+ if (++i >= clump_size) {
+ hex_stream << " ";
+ i = 0;
+ }
+ }
+ return hex_stream.str();
+}
+
+string binary_from_hex (string input) {
+ stringstream hex_stream;
+ uint8_t aByte; // each byte as we grab it
+ string result = "";
+ string holder_string = "";
+
+ hex_stream.str(input);
+ hex_stream.width(2);
+ while (!hex_stream.eof()) {
+ hex_stream >> skipws >> setw(2) >> holder_string;
+ try { // TODO: May not catch all bad-chars.
+ aByte = stoi(holder_string, 0, 16);
+ }
+ catch (const invalid_argument &arg_err) {
+ cerr << "Error 2345: Non-hexadecimal character found in binary-data string ("
+ << arg_err.what() << endl;
+ exit (2345);
+ }
+ result += aByte;
+ }
+ return result;
+}
diff --git a/tf_fuzz/utility/string_ops.hpp b/tf_fuzz/utility/string_ops.hpp
new file mode 100644
index 0000000..83e4d9a
--- /dev/null
+++ b/tf_fuzz/utility/string_ops.hpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef STRING_OPS_HPP
+#define STRING_OPS_HPP
+
+#include <cstddef>
+#include <string>
+
+using namespace std;
+
+// Replace first occurrence of find_str within orig of replace_str:
+size_t find_replace_1st (const string &find_str, const string &replace_str,
+ string &orig);
+
+// Replace all occurrences of find_str in "this" string, with replace_str:
+size_t find_replace_all (const string &find_str, const string &replace_str,
+ string &orig);
+
+/* In both of the above string-replacement functions, the return value is start
+ offset to the (last) occurrence of "find_str" within "orig." */
+
+/* formalize() turns an abbreviated, "human" name for a PSA setting into its
+ presumed official name. Examples:
+ "export" with prefix "PSA_KEY_USAGE_" becomes "PSA_KEY_USAGE_EXPORT".
+ "generic_error" with prefix "PSA_ERROR_" becomes "PSA_ERROR_GENERIC_ERROR".
+ "PSA_ERROR_INVALID_ARGUMENT" stays unchanged as "PSA_ERROR_INVALID_ARGUMENT".
+*/
+string formalize (string input, string prefix);
+
+/* string_or_hex() takes a string (e.g., describing a key's "material" -- data),
+ and:
+ * If it "appears to be" alphanumeric, then returns it unaltered.
+ * Otherwise, if it "appears to be binary data, it returns a new string of
+ it as hex digits.
+ * clump_size is how many bytes to clump together between spaces */
+string string_or_hex (string input, int clump_size);
+
+/* binary_from_hex() takes a string of hex characters, and returns a string
+ containing those raw byte values (i.e., not human-readable, and not really
+ a string in the usual sense of the word). In the future, it would be good
+ to address binary data better. */
+string binary_from_hex (string input);
+
+#endif // #ifndef STRING_OPS_HPP
diff --git a/tf_fuzz/utility/string_ops.o b/tf_fuzz/utility/string_ops.o
new file mode 100644
index 0000000..5f3d9ac
--- /dev/null
+++ b/tf_fuzz/utility/string_ops.o
Binary files differ
diff --git a/tf_fuzz/utility/variables.cpp b/tf_fuzz/utility/variables.cpp
new file mode 100644
index 0000000..ab2a823
--- /dev/null
+++ b/tf_fuzz/utility/variables.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/* This file defines information to track regarding variables in the generated test
+ code. */
+
+#include <string>
+#include <vector>
+#include <list>
+#include <iostream>
+#include <fstream>
+
+#include "class_forwards.hpp"
+
+#include "data_blocks.hpp"
+#include "psa_asset.hpp"
+#include "crypto_asset.hpp"
+#include "psa_call.hpp"
+#include "find_or_create_asset.hpp"
+#include "variables.hpp"
+#include "gibberish.hpp"
+
+/* This project's header files #including other project headers quickly becomes
+ unrealistically complicated. The only solution is for each .cpp to include
+ the headers it needs. However these in particular are mostly axiomatic: Not
+ dependent upon other classes. */
+
+
+using namespace std;
+
+
+/**********************************************************************************
+ Methods of class variable_info follow:
+**********************************************************************************/
+
+variable_info::variable_info (void) // (default constructor)
+{
+ gibberish *gib = new gibberish;
+
+ hash_declared = value_known = false;
+ name = "";
+ length = 100 + (rand() % 800);
+ gib->sentence ((char*) value, (char*) value + length);
+ // TODO: Sizes of random data neesds to be strategized better
+ type = psa_asset_type::unknown;
+ delete gib;
+}
+
+variable_info::variable_info (string var_name, psa_asset_type var_type)
+{ // (constructor with known name and type)
+ gibberish *gib = new gibberish;
+
+ hash_declared = value_known = false;
+ name.assign (var_name);
+ length = 100 + (rand() % 800);
+ gib->sentence ((char*) value, (char*) value + length);
+ // TODO: Sizes of random data needs to be strategized better
+ type = var_type;
+ delete gib;
+}
+
+variable_info::~variable_info (void) // (destructor)
+{}
+
+
+/**********************************************************************************
+ End of methods of class variable_info.
+**********************************************************************************/
diff --git a/tf_fuzz/utility/variables.hpp b/tf_fuzz/utility/variables.hpp
new file mode 100644
index 0000000..886acc3
--- /dev/null
+++ b/tf_fuzz/utility/variables.hpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <string>
+#include <vector>
+
+/* This file defines information to track regarding variables in the generated test
+ code. */
+
+#ifndef VARIABLES_HPP
+#define VARIABLES_HPP
+
+/* This project's header files #including other project headers quickly becomes
+ unrealistically complicated. The only solution is for each .cpp to include
+ the headers it needs. However these in particular are mostly axiomatic: Not
+ dependent upon other classes. */
+
+
+using namespace std;
+
+
+/**********************************************************************************
+ Class variable_info tracks everything we know about a given variable in the
+ generated C code.
+**********************************************************************************/
+
+class variable_info
+{
+public:
+ // Data members:
+ /* The existence of this variable tracker means that the data variable and
+ the length variable have been declared, but there are other variants on
+ this variable that may or may not have been declared already. Thus
+ the *_declared bool(s) below. */
+ bool hash_declared; // true if the hash of this variable has been declared
+ bool value_known; // true if the variable's value can be known in simulation
+ string name; // variable name
+ unsigned char value[2048]; // the current value of the variable
+ int length; // of the variable's value
+ psa_asset_type type; // type of info contained in the variable
+
+ // Methods:
+ variable_info (void); // (default constructor)
+ variable_info ( // (constructor with known name and type)
+ string var_name, psa_asset_type var_type
+ );
+ ~variable_info (void); // (destructor)
+
+protected:
+ // Data members:
+};
+
+
+#endif // VARIABLES_HPP
+
diff --git a/tf_fuzz/utility/variables.o b/tf_fuzz/utility/variables.o
new file mode 100644
index 0000000..bc7772a
--- /dev/null
+++ b/tf_fuzz/utility/variables.o
Binary files differ
diff --git a/tf_fuzz/visualStudio/README b/tf_fuzz/visualStudio/README
new file mode 100644
index 0000000..faa99b2
--- /dev/null
+++ b/tf_fuzz/visualStudio/README
@@ -0,0 +1,10 @@
+This is just things to support running and debug under Microsoft Visual Studio
+(tm).
+
+For more information, please browse to:
+
+ https://ci.trustedfirmware.org/job/tf-m-build-test-nightly/lastSuccessfulBuild/artifact/build-docs/tf-m_documents/install/doc/user_guide/html/docs/user_guides/tf_fuzz/visualStudio_dir.html
+
+--------------
+
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
diff --git a/tf_fuzz/visualStudio/unistd.c b/tf_fuzz/visualStudio/unistd.c
new file mode 100644
index 0000000..7e21cc5
--- /dev/null
+++ b/tf_fuzz/visualStudio/unistd.c
@@ -0,0 +1,3 @@
+int isatty(int arg) {
+ return 0;
+}
\ No newline at end of file
diff --git a/tf_fuzz/visualStudio/unistd.h b/tf_fuzz/visualStudio/unistd.h
new file mode 100644
index 0000000..613ed5f
--- /dev/null
+++ b/tf_fuzz/visualStudio/unistd.h
@@ -0,0 +1,2 @@
+#pragma once
+int isatty(int);
\ No newline at end of file