quickjs-tart

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

test_suite_ctr_drbg.function (17586B)


      1 /* BEGIN_HEADER */
      2 #include "mbedtls/entropy.h"
      3 #include "mbedtls/ctr_drbg.h"
      4 #include "string.h"
      5 #include "ctr.h"
      6 
      7 #if defined(MBEDTLS_THREADING_PTHREAD)
      8 #include "mbedtls/threading.h"
      9 #endif
     10 
     11 /* Modes for ctr_drbg_validate */
     12 enum reseed_mode {
     13     RESEED_NEVER, /* never reseed */
     14     RESEED_FIRST, /* instantiate, reseed, generate, generate */
     15     RESEED_SECOND, /* instantiate, generate, reseed, generate */
     16     RESEED_ALWAYS /* prediction resistance, no explicit reseed */
     17 };
     18 
     19 static size_t test_offset_idx = 0;
     20 static size_t test_max_idx  = 0;
     21 static int mbedtls_test_entropy_func(void *data, unsigned char *buf, size_t len)
     22 {
     23     const unsigned char *p = (unsigned char *) data;
     24     if (test_offset_idx + len > test_max_idx) {
     25         return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
     26     }
     27     memcpy(buf, p + test_offset_idx, len);
     28     test_offset_idx += len;
     29     return 0;
     30 }
     31 
     32 static void ctr_drbg_validate_internal(int reseed_mode, data_t *nonce,
     33                                        int entropy_len_arg, data_t *entropy,
     34                                        data_t *reseed,
     35                                        data_t *add1, data_t *add2,
     36                                        data_t *result)
     37 {
     38     mbedtls_ctr_drbg_context ctx;
     39     mbedtls_ctr_drbg_init(&ctx);
     40     unsigned char buf[64];
     41 
     42     size_t entropy_chunk_len = (size_t) entropy_len_arg;
     43     TEST_ASSERT(entropy_chunk_len <= sizeof(buf));
     44 
     45     test_offset_idx = 0;
     46     test_max_idx = entropy->len;
     47 
     48     /* CTR_DRBG_Instantiate(entropy[:entropy->len], nonce, perso, <ignored>)
     49      * where nonce||perso = nonce[nonce->len] */
     50     mbedtls_ctr_drbg_set_entropy_len(&ctx, entropy_chunk_len);
     51     mbedtls_ctr_drbg_set_nonce_len(&ctx, 0);
     52     TEST_ASSERT(mbedtls_ctr_drbg_seed(
     53                     &ctx,
     54                     mbedtls_test_entropy_func, entropy->x,
     55                     nonce->x, nonce->len) == 0);
     56     if (reseed_mode == RESEED_ALWAYS) {
     57         mbedtls_ctr_drbg_set_prediction_resistance(
     58             &ctx,
     59             MBEDTLS_CTR_DRBG_PR_ON);
     60     }
     61 
     62     if (reseed_mode == RESEED_FIRST) {
     63         /* CTR_DRBG_Reseed(entropy[idx:idx+entropy->len],
     64          *                 reseed[:reseed->len]) */
     65         TEST_ASSERT(mbedtls_ctr_drbg_reseed(
     66                         &ctx,
     67                         reseed->x, reseed->len) == 0);
     68     }
     69 
     70     /* CTR_DRBG_Generate(result->len * 8 bits, add1[:add1->len]) -> buf */
     71     /* Then reseed if prediction resistance is enabled. */
     72     TEST_ASSERT(mbedtls_ctr_drbg_random_with_add(
     73                     &ctx,
     74                     buf, result->len,
     75                     add1->x, add1->len) == 0);
     76 
     77 
     78     if (reseed_mode == RESEED_SECOND) {
     79         /* CTR_DRBG_Reseed(entropy[idx:idx+entropy->len],
     80          *                 reseed[:reseed->len]) */
     81         TEST_ASSERT(mbedtls_ctr_drbg_reseed(
     82                         &ctx,
     83                         reseed->x, reseed->len) == 0);
     84     }
     85 
     86     /* CTR_DRBG_Generate(result->len * 8 bits, add2->x[:add2->len]) -> buf */
     87     /* Then reseed if prediction resistance is enabled. */
     88     TEST_ASSERT(mbedtls_ctr_drbg_random_with_add(
     89                     &ctx,
     90                     buf, result->len,
     91                     add2->x, add2->len) == 0);
     92     TEST_ASSERT(memcmp(buf, result->x, result->len) == 0);
     93 
     94 exit:
     95     mbedtls_ctr_drbg_free(&ctx);
     96 }
     97 
     98 static const int thread_random_reps = 10;
     99 void *thread_random_function(void *ctx); /* only used conditionally in ctr_drbg_threads */
    100 void *thread_random_function(void *ctx)
    101 {
    102     unsigned char out[16];
    103     memset(out, 0, sizeof(out));
    104 
    105     for (int i = 0; i < thread_random_reps; i++) {
    106         TEST_EQUAL(mbedtls_ctr_drbg_random((mbedtls_ctr_drbg_context *) ctx, out, sizeof(out)), 0);
    107     }
    108 
    109 exit:
    110     return NULL;
    111 }
    112 /* END_HEADER */
    113 
    114 /* BEGIN_DEPENDENCIES
    115  * depends_on:MBEDTLS_CTR_DRBG_C
    116  * END_DEPENDENCIES
    117  */
    118 
    119 /* BEGIN_CASE */
    120 void ctr_drbg_special_behaviours()
    121 {
    122     mbedtls_ctr_drbg_context ctx;
    123     unsigned char output[512];
    124     unsigned char additional[512];
    125 
    126     mbedtls_ctr_drbg_init(&ctx);
    127     memset(output, 0, sizeof(output));
    128     memset(additional, 0, sizeof(additional));
    129 
    130     TEST_ASSERT(mbedtls_ctr_drbg_random_with_add(&ctx,
    131                                                  output, MBEDTLS_CTR_DRBG_MAX_REQUEST + 1,
    132                                                  additional, 16) ==
    133                 MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG);
    134     TEST_ASSERT(mbedtls_ctr_drbg_random_with_add(&ctx,
    135                                                  output, 16,
    136                                                  additional, MBEDTLS_CTR_DRBG_MAX_INPUT + 1) ==
    137                 MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG);
    138 
    139     TEST_ASSERT(mbedtls_ctr_drbg_reseed(&ctx, additional,
    140                                         MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + 1) ==
    141                 MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG);
    142 
    143     mbedtls_ctr_drbg_set_entropy_len(&ctx, ~0);
    144     TEST_ASSERT(mbedtls_ctr_drbg_reseed(&ctx, additional,
    145                                         MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) ==
    146                 MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG);
    147 exit:
    148     mbedtls_ctr_drbg_free(&ctx);
    149 }
    150 /* END_CASE */
    151 
    152 
    153 /* BEGIN_CASE */
    154 void ctr_drbg_validate_no_reseed(data_t *add_init, data_t *entropy,
    155                                  data_t *add1, data_t *add2,
    156                                  data_t *result_string)
    157 {
    158     data_t empty = { 0, 0 };
    159     AES_PSA_INIT();
    160     ctr_drbg_validate_internal(RESEED_NEVER, add_init,
    161                                entropy->len, entropy,
    162                                &empty, add1, add2,
    163                                result_string);
    164     AES_PSA_DONE();
    165     goto exit; // goto is needed to avoid warning ( no test assertions in func)
    166 }
    167 /* END_CASE */
    168 
    169 /* BEGIN_CASE */
    170 void ctr_drbg_validate_pr(data_t *add_init, data_t *entropy,
    171                           data_t *add1, data_t *add2,
    172                           data_t *result_string)
    173 {
    174     data_t empty = { 0, 0 };
    175     AES_PSA_INIT();
    176     ctr_drbg_validate_internal(RESEED_ALWAYS, add_init,
    177                                entropy->len / 3, entropy,
    178                                &empty, add1, add2,
    179                                result_string);
    180     AES_PSA_DONE();
    181     goto exit; // goto is needed to avoid warning ( no test assertions in func)
    182 }
    183 /* END_CASE */
    184 
    185 /* BEGIN_CASE */
    186 void ctr_drbg_validate_reseed_between(data_t *add_init, data_t *entropy,
    187                                       data_t *add1, data_t *add_reseed,
    188                                       data_t *add2, data_t *result_string)
    189 {
    190     AES_PSA_INIT();
    191     ctr_drbg_validate_internal(RESEED_SECOND, add_init,
    192                                entropy->len / 2, entropy,
    193                                add_reseed, add1, add2,
    194                                result_string);
    195     AES_PSA_DONE();
    196     goto exit; // goto is needed to avoid warning ( no test assertions in func)
    197 }
    198 /* END_CASE */
    199 
    200 /* BEGIN_CASE */
    201 void ctr_drbg_validate_reseed_first(data_t *add_init, data_t *entropy,
    202                                     data_t *add1, data_t *add_reseed,
    203                                     data_t *add2, data_t *result_string)
    204 {
    205     AES_PSA_INIT();
    206     ctr_drbg_validate_internal(RESEED_FIRST, add_init,
    207                                entropy->len / 2, entropy,
    208                                add_reseed, add1, add2,
    209                                result_string);
    210     AES_PSA_DONE();
    211     goto exit; // goto is needed to avoid warning ( no test assertions in func)
    212 }
    213 /* END_CASE */
    214 
    215 /* BEGIN_CASE */
    216 void ctr_drbg_entropy_strength(int expected_bit_strength)
    217 {
    218     unsigned char entropy[/*initial entropy*/ MBEDTLS_CTR_DRBG_ENTROPY_LEN +
    219                           /*nonce*/ MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN +
    220                           /*reseed*/ MBEDTLS_CTR_DRBG_ENTROPY_LEN];
    221     mbedtls_ctr_drbg_context ctx;
    222     size_t last_idx;
    223     size_t byte_strength = expected_bit_strength / 8;
    224 
    225     mbedtls_ctr_drbg_init(&ctx);
    226 
    227     AES_PSA_INIT();
    228     test_offset_idx = 0;
    229     test_max_idx = sizeof(entropy);
    230     memset(entropy, 0, sizeof(entropy));
    231 
    232     /* The initial seeding must grab at least byte_strength bytes of entropy
    233      * for the entropy input and byte_strength/2 bytes for a nonce. */
    234     TEST_ASSERT(mbedtls_ctr_drbg_seed(&ctx,
    235                                       mbedtls_test_entropy_func, entropy,
    236                                       NULL, 0) == 0);
    237     TEST_ASSERT(test_offset_idx >= (byte_strength * 3 + 1) / 2);
    238     last_idx = test_offset_idx;
    239 
    240     /* A reseed must grab at least byte_strength bytes of entropy. */
    241     TEST_ASSERT(mbedtls_ctr_drbg_reseed(&ctx, NULL, 0) == 0);
    242     TEST_ASSERT(test_offset_idx - last_idx >= byte_strength);
    243 
    244 exit:
    245     mbedtls_ctr_drbg_free(&ctx);
    246     AES_PSA_DONE();
    247 }
    248 /* END_CASE */
    249 
    250 /* BEGIN_CASE */
    251 void ctr_drbg_entropy_usage(int entropy_nonce_len)
    252 {
    253     unsigned char out[16];
    254     unsigned char add[16];
    255     unsigned char entropy[1024];
    256     mbedtls_ctr_drbg_context ctx;
    257     size_t i, reps = 10;
    258     size_t expected_idx = 0;
    259 
    260     mbedtls_ctr_drbg_init(&ctx);
    261 
    262     AES_PSA_INIT();
    263 
    264     test_offset_idx = 0;
    265     test_max_idx = sizeof(entropy);
    266     memset(entropy, 0, sizeof(entropy));
    267     memset(out, 0, sizeof(out));
    268     memset(add, 0, sizeof(add));
    269 
    270     if (entropy_nonce_len >= 0) {
    271         TEST_ASSERT(mbedtls_ctr_drbg_set_nonce_len(&ctx, entropy_nonce_len) == 0);
    272     }
    273 
    274     /* Set reseed interval before seed */
    275     mbedtls_ctr_drbg_set_reseed_interval(&ctx, 2 * reps);
    276 
    277     /* Init must use entropy */
    278     TEST_ASSERT(mbedtls_ctr_drbg_seed(&ctx, mbedtls_test_entropy_func, entropy, NULL, 0) == 0);
    279     expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_LEN;
    280     if (entropy_nonce_len >= 0) {
    281         expected_idx += entropy_nonce_len;
    282     } else {
    283         expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN;
    284     }
    285     TEST_EQUAL(test_offset_idx, expected_idx);
    286 
    287     /* By default, PR is off, and reseed interval was set to
    288      * 2 * reps so the next few calls should not use entropy */
    289     for (i = 0; i < reps; i++) {
    290         TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out) - 4) == 0);
    291         TEST_ASSERT(mbedtls_ctr_drbg_random_with_add(&ctx, out, sizeof(out) - 4,
    292                                                      add, sizeof(add)) == 0);
    293     }
    294     TEST_EQUAL(test_offset_idx, expected_idx);
    295 
    296     /* While at it, make sure we didn't write past the requested length */
    297     TEST_ASSERT(out[sizeof(out) - 4] == 0);
    298     TEST_ASSERT(out[sizeof(out) - 3] == 0);
    299     TEST_ASSERT(out[sizeof(out) - 2] == 0);
    300     TEST_ASSERT(out[sizeof(out) - 1] == 0);
    301 
    302     /* There have been 2 * reps calls to random. The next call should reseed */
    303     TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)) == 0);
    304     expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_LEN;
    305     TEST_EQUAL(test_offset_idx, expected_idx);
    306 
    307     /* Set reseed interval after seed */
    308     mbedtls_ctr_drbg_set_reseed_interval(&ctx, 4 * reps + 1);
    309 
    310     /* The next few calls should not reseed */
    311     for (i = 0; i < (2 * reps); i++) {
    312         TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)) == 0);
    313         TEST_ASSERT(mbedtls_ctr_drbg_random_with_add(&ctx, out, sizeof(out),
    314                                                      add, sizeof(add)) == 0);
    315     }
    316     TEST_EQUAL(test_offset_idx, expected_idx);
    317 
    318     /* Call update with too much data (sizeof(entropy) > MAX(_SEED)_INPUT).
    319      * Make sure it's detected as an error and doesn't cause memory
    320      * corruption. */
    321     TEST_ASSERT(mbedtls_ctr_drbg_update(
    322                     &ctx, entropy, sizeof(entropy)) != 0);
    323 
    324     /* Now enable PR, so the next few calls should all reseed */
    325     mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_ON);
    326     TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)) == 0);
    327     expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_LEN;
    328     TEST_EQUAL(test_offset_idx, expected_idx);
    329 
    330     /* Finally, check setting entropy_len */
    331     mbedtls_ctr_drbg_set_entropy_len(&ctx, 42);
    332     TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)) == 0);
    333     expected_idx += 42;
    334     TEST_EQUAL(test_offset_idx, expected_idx);
    335 
    336     mbedtls_ctr_drbg_set_entropy_len(&ctx, 13);
    337     TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)) == 0);
    338     expected_idx += 13;
    339     TEST_EQUAL(test_offset_idx, expected_idx);
    340 
    341 exit:
    342     mbedtls_ctr_drbg_free(&ctx);
    343     AES_PSA_DONE();
    344 }
    345 /* END_CASE */
    346 
    347 /* BEGIN_CASE depends_on:MBEDTLS_THREADING_PTHREAD:!MBEDTLS_CTR_DRBG_USE_128_BIT_KEY:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
    348 void ctr_drbg_threads(data_t *expected_result, int reseed, int arg_thread_count)
    349 {
    350     size_t thread_count = (size_t) arg_thread_count;
    351     mbedtls_test_thread_t *threads = NULL;
    352 
    353     unsigned char out[16];
    354     unsigned char *entropy = NULL;
    355 
    356     const size_t n_random_calls = thread_count * thread_random_reps + 1;
    357 
    358     /* This is a known-answer test, and although tests use a mock entropy
    359      * function the input entropy length will still affect the output.
    360      * We therefore need to pick a fixed entropy length, rather than using the
    361      * default entropy length (MBEDTLS_CTR_DRBG_ENTROPY_LEN). We've chosen to
    362      * use the default value of MBEDTLS_CTR_DRBG_ENTROPY_LEN for SHA-512,
    363      * as this was the value used when the expected answers were calculated. */
    364     const size_t entropy_len = 48;
    365 
    366     mbedtls_ctr_drbg_context ctx;
    367     mbedtls_ctr_drbg_init(&ctx);
    368 
    369     AES_PSA_INIT();
    370 
    371     TEST_CALLOC(threads, sizeof(mbedtls_test_thread_t) * thread_count);
    372     memset(out, 0, sizeof(out));
    373 
    374     test_offset_idx = 0;
    375 
    376     /* Need to set a non-default fixed entropy len, to ensure same output across
    377      * all configs - see above for details. */
    378     mbedtls_ctr_drbg_set_entropy_len(&ctx, entropy_len);
    379 
    380     if (reseed == 0) {
    381         mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_OFF);
    382         mbedtls_ctr_drbg_set_reseed_interval(&ctx, n_random_calls + 1);
    383 
    384         TEST_CALLOC(entropy, entropy_len + MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN);
    385         test_max_idx = entropy_len + MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN;
    386     } else {
    387         const size_t entropy_size = ((n_random_calls + 1) * entropy_len)
    388                                     + MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN;
    389 
    390         mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_ON);
    391 
    392         TEST_CALLOC(entropy, entropy_size);
    393         test_max_idx = entropy_size;
    394     }
    395 
    396     TEST_EQUAL(
    397         mbedtls_ctr_drbg_seed(&ctx, mbedtls_test_entropy_func, entropy, NULL, 0),
    398         0);
    399 
    400     for (size_t i = 0; i < thread_count; i++) {
    401         TEST_EQUAL(
    402             mbedtls_test_thread_create(&threads[i],
    403                                        thread_random_function, (void *) &ctx),
    404             0);
    405     }
    406 
    407     for (size_t i = 0; i < thread_count; i++) {
    408         TEST_EQUAL(mbedtls_test_thread_join(&threads[i]), 0);
    409     }
    410 
    411     /* Take a last output for comparing and thus verifying the DRBG state */
    412     TEST_EQUAL(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)), 0);
    413 
    414     TEST_MEMORY_COMPARE(out, sizeof(out), expected_result->x, expected_result->len);
    415 
    416 exit:
    417     mbedtls_ctr_drbg_free(&ctx);
    418     mbedtls_free(entropy);
    419     mbedtls_free(threads);
    420 
    421     AES_PSA_DONE();
    422 }
    423 /* END_CASE */
    424 
    425 /* BEGIN_CASE depends_on:MBEDTLS_FS_IO */
    426 void ctr_drbg_seed_file(char *path, int ret)
    427 {
    428     mbedtls_ctr_drbg_context ctx;
    429 
    430     mbedtls_ctr_drbg_init(&ctx);
    431 
    432     AES_PSA_INIT();
    433 
    434     TEST_ASSERT(mbedtls_ctr_drbg_seed(&ctx, mbedtls_test_rnd_std_rand,
    435                                       NULL, NULL, 0) == 0);
    436     TEST_ASSERT(mbedtls_ctr_drbg_write_seed_file(&ctx, path) == ret);
    437     TEST_ASSERT(mbedtls_ctr_drbg_update_seed_file(&ctx, path) == ret);
    438 
    439 exit:
    440     mbedtls_ctr_drbg_free(&ctx);
    441     AES_PSA_DONE();
    442 }
    443 /* END_CASE */
    444 
    445 /* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
    446 void ctr_drbg_selftest()
    447 {
    448     AES_PSA_INIT();
    449     TEST_ASSERT(mbedtls_ctr_drbg_self_test(1) == 0);
    450     AES_PSA_DONE();
    451 }
    452 /* END_CASE */
    453 
    454 /* BEGIN_CASE */
    455 void ctr_increment_rollover()
    456 {
    457     uint8_t c[16];
    458     uint8_t r[16];
    459 
    460     // test all increments from 2^n - 1 to 2^n (i.e. where we roll over into the next bit)
    461     for (int n = 0; n <= 128; n++) {
    462         memset(c, 0, 16);
    463         memset(r, 0, 16);
    464 
    465         // set least significant (highest address) n bits to 1, i.e. generate (2^n - 1)
    466         for (int i = 0; i < n; i++) {
    467             int bit = i % 8;
    468             int byte = (i / 8);
    469             c[15 - byte] |= 1 << bit;
    470         }
    471         // increment to get 2^n
    472         mbedtls_ctr_increment_counter(c);
    473 
    474         // now generate a reference result equal to 2^n - i.e. set only bit (n + 1)
    475         // if n == 127, this will not set any bits (i.e. wraps to 0).
    476         int bit = n % 8;
    477         int byte = n / 8;
    478         if (byte < 16) {
    479             r[15 - byte] = 1 << bit;
    480         }
    481 
    482         TEST_MEMORY_COMPARE(c, 16, r, 16);
    483     }
    484 
    485     uint64_t lsb = 10, msb = 20;
    486     MBEDTLS_PUT_UINT64_BE(msb, c, 0);
    487     MBEDTLS_PUT_UINT64_BE(lsb, c, 8);
    488     memcpy(r, c, 16);
    489     mbedtls_ctr_increment_counter(c);
    490     for (int i = 15; i >= 0; i--) {
    491         r[i] += 1;
    492         if (r[i] != 0) {
    493             break;
    494         }
    495     }
    496     TEST_MEMORY_COMPARE(c, 16, r, 16);
    497 }
    498 /* END_CASE */
    499 
    500 /* BEGIN_CASE */
    501 void ctr_increment(data_t *x)
    502 {
    503     uint8_t c[16];
    504     uint8_t r[16];
    505 
    506     // initialise c and r from test argument
    507     memset(c, 0, 16);
    508     memcpy(c, x->x, x->len);
    509     memcpy(r, c, 16);
    510 
    511     // increment c
    512     mbedtls_ctr_increment_counter(c);
    513     // increment reference
    514     for (int i = 15; i >= 0; i--) {
    515         r[i] += 1;
    516         if (r[i] != 0) {
    517             break;
    518         }
    519     }
    520 
    521     // test that mbedtls_ctr_increment_counter behaviour matches reference
    522     TEST_MEMORY_COMPARE(c, 16, r, 16);
    523 }
    524 /* END_CASE */