quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

test_suite_psa_crypto_init.function (12851B)


      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 static 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 
     24 exit:
     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 
     49 typedef 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;
     55 static 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 
     80 static uint32_t custom_entropy_sources_mask;
     81 static 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. */
     85 static 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 
    135 typedef struct {
    136     int do_init;
    137 } thread_psa_init_ctx_t;
    138 
    139 static 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 
    181 exit:
    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 */
    194 void 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 */
    202 void 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     }
    222 exit:
    223     PSA_DONE();
    224 }
    225 /* END_CASE */
    226 
    227 /* BEGIN_CASE */
    228 void 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 */
    240 void 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     }
    292 exit:
    293 
    294     PSA_DONE();
    295 
    296     mbedtls_free(threads);
    297 }
    298 /* END_CASE */
    299 
    300 /* BEGIN_CASE */
    301 void 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 */
    317 void 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 */
    338 void 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 
    354 exit:
    355     PSA_DONE();
    356 }
    357 /* END_CASE */
    358 
    359 /* BEGIN_CASE depends_on:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
    360 void 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 
    399 exit:
    400     PSA_DONE();
    401 }
    402 /* END_CASE */
    403 
    404 /* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
    405 void 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 
    427 exit:
    428     mbedtls_free(seed);
    429     PSA_DONE();
    430 }
    431 /* END_CASE */