Add multi-threaded unit test
The unit test we add is designed to fail. The goal is to test the tests
and show that they catch the problem. A later commit will fix the unit
test and will make it pass.
Signed-off-by: Janos Follath <janos.follath@arm.com>
diff --git a/tests/suites/test_suite_ctr_drbg.data b/tests/suites/test_suite_ctr_drbg.data
index a72d8af..70206e7 100644
--- a/tests/suites/test_suite_ctr_drbg.data
+++ b/tests/suites/test_suite_ctr_drbg.data
@@ -1096,5 +1096,11 @@
CTR_DRBG Special Behaviours
ctr_drbg_special_behaviours:
+CTR_DRBG Threads: no reseed
+ctr_drbg_threads:"1fafa98bc83d95e10f2d5ed339a553e1":10000
+
+CTR_DRBG Threads: reseed
+ctr_drbg_threads:"0d2dda60286dc738ddcc2dd3520bb988":25
+
CTR_DRBG self test
ctr_drbg_selftest:
diff --git a/tests/suites/test_suite_ctr_drbg.function b/tests/suites/test_suite_ctr_drbg.function
index 066e70b..bdf3dca 100644
--- a/tests/suites/test_suite_ctr_drbg.function
+++ b/tests/suites/test_suite_ctr_drbg.function
@@ -90,6 +90,19 @@
mbedtls_ctr_drbg_free(&ctx);
}
+static const int thread_random_reps = 10;
+void *thread_random_function( void* ctx )
+{
+ unsigned char out[16];
+ memset(out, 0, sizeof(out));
+
+ for(int i = 0; i < thread_random_reps; i++) {
+ TEST_EQUAL(mbedtls_ctr_drbg_random_with_add((mbedtls_ctr_drbg_context*) ctx, out, sizeof(out), NULL, 0), 0);
+ }
+
+exit:
+ return NULL;
+}
/* END_HEADER */
/* BEGIN_DEPENDENCIES
@@ -325,6 +338,57 @@
}
/* END_CASE */
+/* BEGIN_CASE depends_on:MBEDTLS_THREADING_PTHREAD */
+void ctr_drbg_threads(data_t *expected_result, int reseed_interval)
+{
+#define THREAD_CNT 5
+ pthread_t threads[THREAD_CNT];
+
+ unsigned char out[16];
+ memset(out, 0, sizeof(out));
+
+ unsigned char entropy[1024];
+ memset(entropy, 0, sizeof(entropy));
+
+ test_offset_idx = 0;
+ test_max_idx = sizeof(entropy);
+
+ mbedtls_ctr_drbg_context ctx;
+ mbedtls_ctr_drbg_init(&ctx);
+
+ mbedtls_ctr_drbg_set_reseed_interval(&ctx, reseed_interval);
+
+ /* There are too many calls in this test to conveniently provide enough
+ * entropy for this to be on. Test cases can trigger reseeding by setting
+ * \p reseed_interval appropriately. */
+ mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_OFF);
+
+ TEST_EQUAL(
+ mbedtls_ctr_drbg_seed(&ctx, mbedtls_test_entropy_func, entropy, NULL, 0),
+ 0);
+
+ for (size_t i = 0; i < THREAD_CNT; i++) {
+ TEST_EQUAL(
+ pthread_create(&threads[i], NULL,
+ thread_random_function, (void*) &ctx),
+ 0);
+ }
+
+ for (size_t i = 0; i < THREAD_CNT; i++) {
+ TEST_EQUAL(pthread_join(threads[i], NULL), 0);
+ }
+
+ /* Take a last output for comparing and thus verifying the DRBG state */
+ TEST_EQUAL(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)), 0);
+
+ TEST_MEMORY_COMPARE(out, sizeof(out), expected_result->x, expected_result->len);
+
+exit:
+ mbedtls_ctr_drbg_free(&ctx);
+}
+#undef THREAD_CNT
+/* END_CASE */
+
/* BEGIN_CASE depends_on:MBEDTLS_FS_IO */
void ctr_drbg_seed_file(char *path, int ret)
{