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