tf_fuzz: add new crypto key generation model
* Add a new model of what it means for a crypto policy to be valid. This
fixes the simulation of psa_generate_key() calls, which TF-Fuzz
currently cannot accurately predict.
The PSA Crypto properties modelled are whether an algorithm and key
type are compatible, whether a key type/ algorithm are disabled, and
what key sizes are allowed.
Although the PSA Crypto specification has additional, more complicated
requirements for policies and keys, this commit only implements what
is necessary for predicting the outcome of psa_generate_key(), and not
requirements that make a key useless but still valid or involve
features not yet in TF-M or MbedTLS.
* Improve the way in which policies are filled in, and allow policies to
be updated at simulation time using the value of a named policy asset.
Information about other assets and calls is not accessible during
parse time when the key policy is usually filled in. However, this is
required for the improved simulation of psa_generate_key calls. This
is because policy information for generate key calls come from a named
policy created earlier in the test file.
* Add valid flag to set-policy calls, allowing the creation of a random
valid policy. For example, see demo/36.test.
* Add demo/36.test. This test generates a policy with a (roughly) even
chance of being valid or invalid and then tries to generate a key
using it.
Running this test a large number of times (~300) succeeds with the
changes in this commit, showing that TF-Fuzz can now accurately
predict the outcome of psa_generate_key calls.
Change-Id: Ia40ff893db50b8d2c579d975aa23341b7aab004d
Signed-off-by: Nik Dewally <Nik.Dewally@arm.com>
diff --git a/tf_fuzz/tfz-cpp/crypto_model/crypto_model.hpp b/tf_fuzz/tfz-cpp/crypto_model/crypto_model.hpp
new file mode 100644
index 0000000..0d3bf92
--- /dev/null
+++ b/tf_fuzz/tfz-cpp/crypto_model/crypto_model.hpp
@@ -0,0 +1,100 @@
+/* Copyright (c) 2024 Arm Limited. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+// crypto_model.hpp
+#pragma once
+
+#include <string>
+#include <vector>
+#include "crypto_model_internal.hpp"
+
+/*
+ * `crypto_model` contains information about crypto key types, algorithms, and
+ * attributes, and their compatabilities with each-other.
+ */
+namespace crypto_model {
+
+// forward declarations
+class key_type;
+class algorithm;
+
+algorithm& get_algorithm(std::string);
+key_type& get_key_type(std::string);
+
+algorithm& get_random_hash_algorithm();
+
+algorithm& get_random_algorithm();
+
+key_type& get_random_key_type();
+
+uint get_random_key_size();
+
+//! Initialises the crypto model.
+void init_crypto_model();
+
+
+// Classes to hold data.
+class algorithm {
+ friend void crypto_model::init_crypto_model();
+ friend void crypto_model::internal::define_algorithm(std::string,bool,bool);
+
+public:
+ algorithm();
+ ~algorithm();
+
+ std::string get_string();
+
+ // Gets the header value form of the algorithm, with a random hash function
+ // filled in if needed.
+ std::string get_string_with_hash();
+ bool is_enabled();
+
+ bool is_hash_algorithm();
+ bool requires_hash();
+
+ bool valid_for_key_type(key_type&);
+ key_type& random_valid_key_type();
+
+private:
+
+ std::string name;
+ std::vector<std::string> allowed_key_types;
+ bool requires_hash_flag;
+ bool is_hash_algorithm_flag;
+ bool enabled=true;
+};
+
+class key_type {
+ friend void crypto_model::init_crypto_model();
+ friend void crypto_model::internal::define_key_type(std::string, std::vector<uint>, uint, uint);
+
+public:
+ key_type();
+ ~key_type();
+
+ std::string get_string();
+ bool is_enabled();
+
+ bool is_allowed_algorithm(algorithm&);
+ algorithm& random_allowed_algorithm();
+ bool is_valid_key_size(uint size);
+ uint get_random_valid_key_size();
+
+
+private:
+
+ std::string name;
+
+ // If non empty, the key size must be one of the values in this vector.
+ std::vector<uint> allowed_key_sizes_bits;
+ uint max_key_size_bits;
+ uint min_key_size_bits;
+
+ std::vector<std::string> allowed_algorithms;
+
+ bool enabled=true;
+};
+
+} // namespace crypto_model