TF_Fuzz

…/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>/tf-m-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.

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 tf-m-tools/tf_fuzz
    ./generate_test_suite.sh $TF-M_ROOT/../tf-m-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):

-DTFM_FUZZER_TOOL_TESTS=1
-DTFM_FUZZER_TOOL_TESTS_CMAKE_INC_PATH=$TF-M_ROOT/../tf-m-tests/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.