Add a concurrent key generation test function

Split into n threads, each thread will repeatedly generate,
exercise and destroy a key.
Then join the threads, and ensure using PSA_DONE that no keys still exist.

Signed-off-by: Ryan Everett <ryan.everett@arm.com>
This commit is contained in:
Ryan 2024-03-01 17:24:04 +00:00 committed by Ryan Everett
parent 8a2062c538
commit 3a1b786d5d

View File

@ -28,6 +28,10 @@
#define TEST_DRIVER_LOCATION 0x7fffff
#endif
#if defined(MBEDTLS_THREADING_PTHREAD)
#include "mbedtls/threading.h"
#endif
/* If this comes up, it's a bug in the test code or in the test data. */
#define UNUSED 0xdeadbeef
@ -1333,6 +1337,66 @@ exit:
return 0;
}
#if defined(MBEDTLS_THREADING_PTHREAD)
typedef struct generate_key_context {
psa_key_type_t type;
psa_key_usage_t usage;
size_t bits;
psa_algorithm_t alg;
psa_status_t expected_status;
psa_key_attributes_t *attributes;
int is_large_key;
int reps;
}
generate_key_context;
void *thread_generate_key(void *ctx)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_attributes_t got_attributes = PSA_KEY_ATTRIBUTES_INIT;
generate_key_context *gkc = (struct generate_key_context *) ctx;
/* If there are race conditions, it is likely the case that they do not
* arise every time the code runs. We repeat the code to increase the
* chance that any race conditions will be hit. */
for (int n = 0; n < gkc->reps; n++) {
/* Generate a key */
psa_status_t status = psa_generate_key(gkc->attributes, &key);
if (gkc->is_large_key > 0) {
TEST_ASSUME(status != PSA_ERROR_INSUFFICIENT_MEMORY);
}
TEST_EQUAL(status, gkc->expected_status);
if (gkc->expected_status != PSA_SUCCESS) {
PSA_ASSERT(psa_destroy_key(key));
goto exit;
}
/* Test the key information */
PSA_ASSERT(psa_get_key_attributes(key, &got_attributes));
TEST_EQUAL(psa_get_key_type(&got_attributes), gkc->type);
TEST_EQUAL(psa_get_key_bits(&got_attributes), gkc->bits);
/* Do something with the key according
* to its type and permitted usage. */
if (!mbedtls_test_psa_exercise_key(key, gkc->usage, gkc->alg)) {
psa_destroy_key(key);
goto exit;
}
psa_reset_key_attributes(&got_attributes);
PSA_ASSERT(psa_destroy_key(key));
}
exit:
/*
* Key attributes may have been returned by psa_get_key_attributes()
* thus reset them as required.
*/
psa_reset_key_attributes(&got_attributes);
return NULL;
}
#endif /* MBEDTLS_THREADING_PTHREAD */
/* END_HEADER */
/* BEGIN_DEPENDENCIES
@ -9783,6 +9847,59 @@ exit:
}
/* END_CASE */
#if defined MBEDTLS_THREADING_PTHREAD
/* BEGIN_CASE depends_on:MBEDTLS_THREADING_PTHREAD */
void concurrently_generate_keys(int type_arg,
int bits_arg,
int usage_arg,
int alg_arg,
int expected_status_arg,
int is_large_key_arg,
int arg_thread_count,
int reps_arg)
{
size_t thread_count = (size_t) arg_thread_count;
mbedtls_test_thread_t *threads = NULL;
generate_key_context gkc;
gkc.type = type_arg;
gkc.usage = usage_arg;
gkc.bits = bits_arg;
gkc.alg = alg_arg;
gkc.expected_status = expected_status_arg;
gkc.is_large_key = is_large_key_arg;
gkc.reps = reps_arg;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, usage_arg);
psa_set_key_algorithm(&attributes, alg_arg);
psa_set_key_type(&attributes, type_arg);
psa_set_key_bits(&attributes, bits_arg);
gkc.attributes = &attributes;
TEST_CALLOC(threads, sizeof(mbedtls_test_thread_t) * thread_count);
/* Split threads to generate key then destroy key. */
for (size_t i = 0; i < thread_count; i++) {
TEST_EQUAL(
mbedtls_test_thread_create(&threads[i], thread_generate_key,
(void *) &gkc), 0);
}
/* Join threads. */
for (size_t i = 0; i < thread_count; i++) {
TEST_EQUAL(mbedtls_test_thread_join(&threads[i]), 0);
}
exit:
mbedtls_free(threads);
PSA_DONE();
}
/* END_CASE */
#endif
/* BEGIN_CASE */
void generate_key(int type_arg,
int bits_arg,