Add key_destroyable parameter to mbedtls_test_psa_exercise_key

This will allow us to use this smoke test to ensure that key slot content reads are
only performed when we are registered to read a full slot. We will destroy the key
on another thread while the key is being exercised, and fail the test if an unexpected
error code is hit. Future commits will incrementally implement this new parameter.

All current usages of this function have this parameter set to 0, in which case
the new behaviour must be the same as the old behaviour

Signed-off-by: Ryan Everett <ryan.everett@arm.com>
diff --git a/tests/include/test/psa_exercise_key.h b/tests/include/test/psa_exercise_key.h
index 44f5c08..fa57d88 100644
--- a/tests/include/test/psa_exercise_key.h
+++ b/tests/include/test/psa_exercise_key.h
@@ -209,18 +209,26 @@
  * ```
  * if( ! exercise_key( ... ) ) goto exit;
  * ```
+ * To use this function for multi-threaded tests where the key
+ * may be destroyed at any point: call this function with key_destroyable set
+ * to 1, while another thread calls psa_destroy_key on the same key;
+ * this will test whether destroying the key in use leads to any corruption.
  *
- * \param key       The key to exercise. It should be capable of performing
- *                  \p alg.
- * \param usage     The usage flags to assume.
- * \param alg       The algorithm to exercise.
+ * \param key               The key to exercise. It should be capable of performing
+ *                          \p alg.
+ * \param usage             The usage flags to assume.
+ * \param alg               The algorithm to exercise.
+ * \param key_destroyable   If set to 1, a failure due to the key not existing
+ *                          or the key being destroyed mid-operation will only
+ *                          be reported if the error code is unexpected.
  *
  * \retval 0 The key failed the smoke tests.
  * \retval 1 The key passed the smoke tests.
  */
 int mbedtls_test_psa_exercise_key(mbedtls_svc_key_id_t key,
                                   psa_key_usage_t usage,
-                                  psa_algorithm_t alg);
+                                  psa_algorithm_t alg,
+                                  int key_destroyable);
 
 psa_key_usage_t mbedtls_test_psa_usage_to_exercise(psa_key_type_t type,
                                                    psa_algorithm_t alg);
diff --git a/tests/src/psa_exercise_key.c b/tests/src/psa_exercise_key.c
index 7b81052..e5cce79 100644
--- a/tests/src/psa_exercise_key.c
+++ b/tests/src/psa_exercise_key.c
@@ -948,38 +948,43 @@
 
 int mbedtls_test_psa_exercise_key(mbedtls_svc_key_id_t key,
                                   psa_key_usage_t usage,
-                                  psa_algorithm_t alg)
+                                  psa_algorithm_t alg,
+                                  int key_destroyable)
 {
     int ok = 0;
 
-    if (!check_key_attributes_sanity(key)) {
+    if (!check_key_attributes_sanity(key, key_destroyable)) {
         return 0;
     }
 
     if (alg == 0) {
         ok = 1; /* If no algorithm, do nothing (used for raw data "keys"). */
     } else if (PSA_ALG_IS_MAC(alg)) {
-        ok = exercise_mac_key(key, usage, alg);
+        ok = exercise_mac_key(key, usage, alg, key_destroyable);
     } else if (PSA_ALG_IS_CIPHER(alg)) {
-        ok = exercise_cipher_key(key, usage, alg);
+        ok = exercise_cipher_key(key, usage, alg, key_destroyable);
     } else if (PSA_ALG_IS_AEAD(alg)) {
-        ok = exercise_aead_key(key, usage, alg);
+        ok = exercise_aead_key(key, usage, alg, key_destroyable);
     } else if (PSA_ALG_IS_SIGN(alg)) {
-        ok = exercise_signature_key(key, usage, alg);
+        ok = exercise_signature_key(key, usage, alg, key_destroyable);
     } else if (PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg)) {
-        ok = exercise_asymmetric_encryption_key(key, usage, alg);
+        ok = exercise_asymmetric_encryption_key(key, usage, alg,
+                                                key_destroyable);
     } else if (PSA_ALG_IS_KEY_DERIVATION(alg)) {
-        ok = exercise_key_derivation_key(key, usage, alg);
+        ok = exercise_key_derivation_key(key, usage, alg, key_destroyable);
     } else if (PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)) {
-        ok = exercise_raw_key_agreement_key(key, usage, alg);
+        ok = exercise_raw_key_agreement_key(key, usage, alg, key_destroyable);
     } else if (PSA_ALG_IS_KEY_AGREEMENT(alg)) {
-        ok = exercise_key_agreement_key(key, usage, alg);
+        ok = exercise_key_agreement_key(key, usage, alg, key_destroyable);
     } else {
         TEST_FAIL("No code to exercise this category of algorithm");
     }
 
-    ok = ok && exercise_export_key(key, usage);
-    ok = ok && exercise_export_public_key(key);
+    ok = ok && exercise_export_key(key,
+                                   usage,
+                                   key_destroyable);
+    ok = ok && exercise_export_public_key(key,
+                                          key_destroyable);
 
 exit:
     return ok;
diff --git a/tests/suites/test_suite_pkparse.function b/tests/suites/test_suite_pkparse.function
index 7dc8413..a06fc30 100644
--- a/tests/suites/test_suite_pkparse.function
+++ b/tests/suites/test_suite_pkparse.function
@@ -57,7 +57,7 @@
     if (mbedtls_test_can_exercise_psa_algorithm(exercise_alg)) {
         TEST_ASSERT(mbedtls_test_psa_exercise_key(psa_key,
                                                   exercise_usage,
-                                                  exercise_alg));
+                                                  exercise_alg, 0));
     }
 
     mbedtls_test_set_step((unsigned long) -1);
diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function
index 1141597..dfddbb9 100644
--- a/tests/suites/test_suite_psa_crypto.function
+++ b/tests/suites/test_suite_psa_crypto.function
@@ -1379,7 +1379,7 @@
 
         /* Do something with the key according
          * to its type and permitted usage. */
-        if (!mbedtls_test_psa_exercise_key(key, gkc->usage, gkc->alg)) {
+        if (!mbedtls_test_psa_exercise_key(key, gkc->usage, gkc->alg, 0)) {
             psa_destroy_key(key);
             goto exit;
         }
@@ -1715,7 +1715,7 @@
      * this doesn't directly validate the implementation, but it still helps
      * by cross-validating the test data with the sanity check code. */
     if (!psa_key_lifetime_is_external(lifetime)) {
-        if (!mbedtls_test_psa_exercise_key(key, usage_arg, 0)) {
+        if (!mbedtls_test_psa_exercise_key(key, usage_arg, 0, 0)) {
             goto exit;
         }
     }
@@ -1853,7 +1853,7 @@
     TEST_EQUAL(psa_get_key_bits(&got_attributes), bits);
 
     /* Do something with the key according to its type and permitted usage. */
-    if (!mbedtls_test_psa_exercise_key(key, usage, alg)) {
+    if (!mbedtls_test_psa_exercise_key(key, usage, alg, 0)) {
         goto exit;
     }
 
@@ -2529,10 +2529,10 @@
     TEST_EQUAL(psa_get_key_algorithm(&got_attributes), alg);
     TEST_EQUAL(psa_get_key_enrollment_algorithm(&got_attributes), alg2);
 
-    if (!mbedtls_test_psa_exercise_key(key, usage, alg)) {
+    if (!mbedtls_test_psa_exercise_key(key, usage, alg, 0)) {
         goto exit;
     }
-    if (!mbedtls_test_psa_exercise_key(key, usage, alg2)) {
+    if (!mbedtls_test_psa_exercise_key(key, usage, alg2, 0)) {
         goto exit;
     }
 
@@ -2663,10 +2663,10 @@
     }
 
     if (!psa_key_lifetime_is_external(target_lifetime)) {
-        if (!mbedtls_test_psa_exercise_key(target_key, expected_usage, expected_alg)) {
+        if (!mbedtls_test_psa_exercise_key(target_key, expected_usage, expected_alg, 0)) {
             goto exit;
         }
-        if (!mbedtls_test_psa_exercise_key(target_key, expected_usage, expected_alg2)) {
+        if (!mbedtls_test_psa_exercise_key(target_key, expected_usage, expected_alg2, 0)) {
             goto exit;
         }
     }
@@ -9233,7 +9233,7 @@
     TEST_EQUAL(psa_get_key_bits(&got_attributes), derived_bits);
 
     /* Exercise the derived key. */
-    if (!mbedtls_test_psa_exercise_key(derived_key, derived_usage, derived_alg)) {
+    if (!mbedtls_test_psa_exercise_key(derived_key, derived_usage, derived_alg, 0)) {
         goto exit;
     }
 
@@ -9941,7 +9941,7 @@
     TEST_EQUAL(psa_get_key_bits(&got_attributes), bits);
 
     /* Do something with the key according to its type and permitted usage. */
-    if (!mbedtls_test_psa_exercise_key(key, usage, alg)) {
+    if (!mbedtls_test_psa_exercise_key(key, usage, alg, 0)) {
         goto exit;
     }
 
@@ -10011,7 +10011,7 @@
 #endif
 
     /* Do something with the key according to its type and permitted usage. */
-    if (!mbedtls_test_psa_exercise_key(key, usage, alg)) {
+    if (!mbedtls_test_psa_exercise_key(key, usage, alg, 0)) {
         goto exit;
     }
 
@@ -10162,7 +10162,7 @@
     }
 
     /* Do something with the key according to its type and permitted usage. */
-    if (!mbedtls_test_psa_exercise_key(key, usage_flags, alg)) {
+    if (!mbedtls_test_psa_exercise_key(key, usage_flags, alg, 0)) {
         goto exit;
     }
 
diff --git a/tests/suites/test_suite_psa_crypto_storage_format.function b/tests/suites/test_suite_psa_crypto_storage_format.function
index bb1e2c6..efaaba5 100644
--- a/tests/suites/test_suite_psa_crypto_storage_format.function
+++ b/tests/suites/test_suite_psa_crypto_storage_format.function
@@ -187,7 +187,7 @@
         TEST_ASSERT(mbedtls_test_psa_exercise_key(
                         key_id,
                         psa_get_key_usage_flags(expected_attributes),
-                        psa_get_key_algorithm(expected_attributes)));
+                        psa_get_key_algorithm(expected_attributes), 0));
     }