1/* BEGIN_HEADER */ 2#include <stdint.h> 3 4#include "psa_crypto_core.h" 5/* Some tests in this module configure entropy sources. */ 6#include "psa_crypto_invasive.h" 7 8#include "mbedtls/entropy.h" 9#include "entropy_poll.h" 10 11#define ENTROPY_MIN_NV_SEED_SIZE \ 12 MAX(MBEDTLS_ENTROPY_MIN_PLATFORM, MBEDTLS_ENTROPY_BLOCK_SIZE) 13 14#include "psa_crypto_random_impl.h" 15#if defined(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE) 16/* PSA crypto uses the HMAC_DRBG module. It reads from the entropy source twice: 17 * once for the initial entropy and once for a nonce. The nonce length is 18 * half the entropy length. For SHA-256, SHA-384 or SHA-512, the 19 * entropy length is 256 per the documentation of mbedtls_hmac_drbg_seed(), 20 * and PSA crypto doesn't support other hashes for HMAC_DRBG. */ 21#define ENTROPY_NONCE_LEN (256 / 2) 22#else 23/* PSA crypto uses the CTR_DRBG module. In some configurations, it needs 24 * to read from the entropy source twice: once for the initial entropy 25 * and once for a nonce. */ 26#include "mbedtls/ctr_drbg.h" 27#define ENTROPY_NONCE_LEN MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN 28#endif 29 30#if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) 31 32typedef struct { 33 size_t threshold; /* Minimum bytes to make mbedtls_entropy_func happy */ 34 size_t max_steps; 35 size_t *length_sequence; 36 size_t step; 37} fake_entropy_state_t; 38static int fake_entropy_source(void *state_arg, 39 unsigned char *output, size_t len, 40 size_t *olen) 41{ 42 fake_entropy_state_t *state = state_arg; 43 size_t i; 44 45 if (state->step >= state->max_steps) { 46 return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; 47 } 48 49 *olen = MIN(len, state->length_sequence[state->step]); 50 for (i = 0; i < *olen; i++) { 51 output[i] = i; 52 } 53 ++state->step; 54 return 0; 55} 56 57#define ENTROPY_SOURCE_PLATFORM 0x00000001 58#define ENTROPY_SOURCE_TIMING 0x00000002 59#define ENTROPY_SOURCE_HARDWARE 0x00000004 60#define ENTROPY_SOURCE_NV_SEED 0x00000008 61#define ENTROPY_SOURCE_FAKE 0x40000000 62 63static uint32_t custom_entropy_sources_mask; 64static fake_entropy_state_t fake_entropy_state; 65 66/* This is a modified version of mbedtls_entropy_init() from entropy.c 67 * which chooses entropy sources dynamically. */ 68static void custom_entropy_init(mbedtls_entropy_context *ctx) 69{ 70 ctx->source_count = 0; 71 memset(ctx->source, 0, sizeof(ctx->source)); 72 73#if defined(MBEDTLS_THREADING_C) 74 mbedtls_mutex_init(&ctx->mutex); 75#endif 76 77 ctx->accumulator_started = 0; 78 mbedtls_md_init(&ctx->accumulator); 79 80#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) 81 if (custom_entropy_sources_mask & ENTROPY_SOURCE_PLATFORM) { 82 mbedtls_entropy_add_source(ctx, mbedtls_platform_entropy_poll, NULL, 83 MBEDTLS_ENTROPY_MIN_PLATFORM, 84 MBEDTLS_ENTROPY_SOURCE_STRONG); 85 } 86#endif 87#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) 88 if (custom_entropy_sources_mask & ENTROPY_SOURCE_HARDWARE) { 89 mbedtls_entropy_add_source(ctx, mbedtls_hardware_poll, NULL, 90 MBEDTLS_ENTROPY_MIN_HARDWARE, 91 MBEDTLS_ENTROPY_SOURCE_STRONG); 92 } 93#endif 94#if defined(MBEDTLS_ENTROPY_NV_SEED) 95 if (custom_entropy_sources_mask & ENTROPY_SOURCE_NV_SEED) { 96 mbedtls_entropy_add_source(ctx, mbedtls_nv_seed_poll, NULL, 97 MBEDTLS_ENTROPY_BLOCK_SIZE, 98 MBEDTLS_ENTROPY_SOURCE_STRONG); 99 ctx->initial_entropy_run = 0; 100 } else { 101 /* Skip the NV seed even though it's compiled in. */ 102 ctx->initial_entropy_run = 1; 103 } 104#endif 105 106 if (custom_entropy_sources_mask & ENTROPY_SOURCE_FAKE) { 107 mbedtls_entropy_add_source(ctx, 108 fake_entropy_source, &fake_entropy_state, 109 fake_entropy_state.threshold, 110 MBEDTLS_ENTROPY_SOURCE_STRONG); 111 } 112} 113 114#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */ 115 116#if defined MBEDTLS_THREADING_PTHREAD 117 118typedef struct { 119 int do_init; 120} thread_psa_init_ctx_t; 121 122static void *thread_psa_init_function(void *ctx) 123{ 124 thread_psa_init_ctx_t *init_context = (thread_psa_init_ctx_t *) ctx; 125 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; 126 uint8_t random[10] = { 0 }; 127 128 if (init_context->do_init) { 129 PSA_ASSERT(psa_crypto_init()); 130 } 131 132 /* If this is a test only thread, then we can assume PSA is being started 133 * up on another thread and thus we cannot know whether the following tests 134 * will be successful or not. These checks are still useful, however even 135 * without checking the return codes as they may show up race conditions on 136 * the flags they check under TSAN.*/ 137 138 /* Test getting if drivers are initialised. */ 139 int can_do = psa_can_do_hash(PSA_ALG_NONE); 140 141 if (init_context->do_init) { 142 TEST_ASSERT(can_do == 1); 143 } 144 145#if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) 146 147 /* Test getting global_data.rng_state. */ 148 status = mbedtls_psa_crypto_configure_entropy_sources(NULL, NULL); 149 150 if (init_context->do_init) { 151 /* Bad state due to entropy sources already being setup in 152 * psa_crypto_init() */ 153 TEST_EQUAL(status, PSA_ERROR_BAD_STATE); 154 } 155#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */ 156 157 /* Test using the PSA RNG ony if we know PSA is up and running. */ 158 if (init_context->do_init) { 159 status = psa_generate_random(random, sizeof(random)); 160 161 TEST_EQUAL(status, PSA_SUCCESS); 162 } 163 164exit: 165 return NULL; 166} 167#endif /* defined MBEDTLS_THREADING_PTHREAD */ 168 169/* END_HEADER */ 170 171/* BEGIN_DEPENDENCIES 172 * depends_on:MBEDTLS_PSA_CRYPTO_C 173 * END_DEPENDENCIES 174 */ 175 176/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ 177void create_nv_seed() 178{ 179 static unsigned char seed[ENTROPY_MIN_NV_SEED_SIZE]; 180 TEST_ASSERT(mbedtls_nv_seed_write(seed, sizeof(seed)) >= 0); 181} 182/* END_CASE */ 183 184/* BEGIN_CASE */ 185void init_deinit(int count) 186{ 187 psa_status_t status; 188 int i; 189 for (i = 0; i < count; i++) { 190 status = psa_crypto_init(); 191 PSA_ASSERT(status); 192 status = psa_crypto_init(); 193 PSA_ASSERT(status); 194 PSA_DONE(); 195 } 196} 197/* END_CASE */ 198 199/* BEGIN_CASE */ 200void deinit_without_init(int count) 201{ 202 int i; 203 for (i = 0; i < count; i++) { 204 PSA_ASSERT(psa_crypto_init()); 205 PSA_DONE(); 206 } 207 PSA_DONE(); 208} 209/* END_CASE */ 210 211/* BEGIN_CASE depends_on:MBEDTLS_THREADING_PTHREAD */ 212void psa_threaded_init(int arg_thread_count) 213{ 214 thread_psa_init_ctx_t init_context; 215 thread_psa_init_ctx_t init_context_2; 216 217 size_t thread_count = (size_t) arg_thread_count; 218 mbedtls_test_thread_t *threads = NULL; 219 220 TEST_CALLOC(threads, sizeof(mbedtls_test_thread_t) * thread_count); 221 222 init_context.do_init = 1; 223 224 /* Test initialising PSA and testing certain protected globals on multiple 225 * threads. */ 226 for (size_t i = 0; i < thread_count; i++) { 227 TEST_EQUAL( 228 mbedtls_test_thread_create(&threads[i], 229 thread_psa_init_function, 230 (void *) &init_context), 231 0); 232 } 233 234 for (size_t i = 0; i < thread_count; i++) { 235 TEST_EQUAL(mbedtls_test_thread_join(&threads[i]), 0); 236 } 237 238 PSA_DONE(); 239 240 init_context_2.do_init = 0; 241 242 /* Test initialising PSA whilst also testing flags on other threads. */ 243 for (size_t i = 0; i < thread_count; i++) { 244 245 if (i & 1) { 246 247 TEST_EQUAL( 248 mbedtls_test_thread_create(&threads[i], 249 thread_psa_init_function, 250 (void *) &init_context), 251 0); 252 } else { 253 TEST_EQUAL( 254 mbedtls_test_thread_create(&threads[i], 255 thread_psa_init_function, 256 (void *) &init_context_2), 257 0); 258 } 259 } 260 261 for (size_t i = 0; i < thread_count; i++) { 262 TEST_EQUAL(mbedtls_test_thread_join(&threads[i]), 0); 263 } 264exit: 265 266 PSA_DONE(); 267 268 mbedtls_free(threads); 269} 270/* END_CASE */ 271 272/* BEGIN_CASE */ 273void validate_module_init_generate_random(int count) 274{ 275 psa_status_t status; 276 uint8_t random[10] = { 0 }; 277 int i; 278 for (i = 0; i < count; i++) { 279 status = psa_crypto_init(); 280 PSA_ASSERT(status); 281 PSA_DONE(); 282 } 283 status = psa_generate_random(random, sizeof(random)); 284 TEST_EQUAL(status, PSA_ERROR_BAD_STATE); 285} 286/* END_CASE */ 287 288/* BEGIN_CASE */ 289void validate_module_init_key_based(int count) 290{ 291 psa_status_t status; 292 uint8_t data[10] = { 0 }; 293 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; 294 mbedtls_svc_key_id_t key = mbedtls_svc_key_id_make(0xdead, 0xdead); 295 int i; 296 297 for (i = 0; i < count; i++) { 298 status = psa_crypto_init(); 299 PSA_ASSERT(status); 300 PSA_DONE(); 301 } 302 psa_set_key_type(&attributes, PSA_KEY_TYPE_RAW_DATA); 303 status = psa_import_key(&attributes, data, sizeof(data), &key); 304 TEST_EQUAL(status, PSA_ERROR_BAD_STATE); 305 TEST_ASSERT(mbedtls_svc_key_id_is_null(key)); 306} 307/* END_CASE */ 308 309/* BEGIN_CASE depends_on:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ 310void custom_entropy_sources(int sources_arg, int expected_init_status_arg) 311{ 312 psa_status_t expected_init_status = expected_init_status_arg; 313 uint8_t random[10] = { 0 }; 314 315 custom_entropy_sources_mask = sources_arg; 316 PSA_ASSERT(mbedtls_psa_crypto_configure_entropy_sources( 317 custom_entropy_init, mbedtls_entropy_free)); 318 319 TEST_EQUAL(psa_crypto_init(), expected_init_status); 320 if (expected_init_status != PSA_SUCCESS) { 321 goto exit; 322 } 323 324 PSA_ASSERT(psa_generate_random(random, sizeof(random))); 325 326exit: 327 PSA_DONE(); 328} 329/* END_CASE */ 330 331/* BEGIN_CASE depends_on:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ 332void fake_entropy_source(int threshold, 333 int amount1, 334 int amount2, 335 int amount3, 336 int amount4, 337 int expected_init_status_arg) 338{ 339 psa_status_t expected_init_status = expected_init_status_arg; 340 uint8_t random[10] = { 0 }; 341 size_t lengths[4]; 342 343 fake_entropy_state.threshold = threshold; 344 fake_entropy_state.step = 0; 345 fake_entropy_state.max_steps = 0; 346 if (amount1 >= 0) { 347 lengths[fake_entropy_state.max_steps++] = amount1; 348 } 349 if (amount2 >= 0) { 350 lengths[fake_entropy_state.max_steps++] = amount2; 351 } 352 if (amount3 >= 0) { 353 lengths[fake_entropy_state.max_steps++] = amount3; 354 } 355 if (amount4 >= 0) { 356 lengths[fake_entropy_state.max_steps++] = amount4; 357 } 358 fake_entropy_state.length_sequence = lengths; 359 360 custom_entropy_sources_mask = ENTROPY_SOURCE_FAKE; 361 PSA_ASSERT(mbedtls_psa_crypto_configure_entropy_sources( 362 custom_entropy_init, mbedtls_entropy_free)); 363 364 TEST_EQUAL(psa_crypto_init(), expected_init_status); 365 if (expected_init_status != PSA_SUCCESS) { 366 goto exit; 367 } 368 369 PSA_ASSERT(psa_generate_random(random, sizeof(random))); 370 371exit: 372 PSA_DONE(); 373} 374/* END_CASE */ 375 376/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ 377void entropy_from_nv_seed(int seed_size_arg, 378 int expected_init_status_arg) 379{ 380 psa_status_t expected_init_status = expected_init_status_arg; 381 uint8_t random[10] = { 0 }; 382 uint8_t *seed = NULL; 383 size_t seed_size = seed_size_arg; 384 385 TEST_CALLOC(seed, seed_size); 386 TEST_ASSERT(mbedtls_nv_seed_write(seed, seed_size) >= 0); 387 388 custom_entropy_sources_mask = ENTROPY_SOURCE_NV_SEED; 389 PSA_ASSERT(mbedtls_psa_crypto_configure_entropy_sources( 390 custom_entropy_init, mbedtls_entropy_free)); 391 392 TEST_EQUAL(psa_crypto_init(), expected_init_status); 393 if (expected_init_status != PSA_SUCCESS) { 394 goto exit; 395 } 396 397 PSA_ASSERT(psa_generate_random(random, sizeof(random))); 398 399exit: 400 mbedtls_free(seed); 401 PSA_DONE(); 402} 403/* END_CASE */ 404