quickjs-tart

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

hmac_drbg.c (18975B)


      1 /*
      2  *  HMAC_DRBG implementation (NIST SP 800-90)
      3  *
      4  *  Copyright The Mbed TLS Contributors
      5  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
      6  */
      7 
      8 /*
      9  *  The NIST SP 800-90A DRBGs are described in the following publication.
     10  *  http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
     11  *  References below are based on rev. 1 (January 2012).
     12  */
     13 
     14 #include "common.h"
     15 
     16 #if defined(MBEDTLS_HMAC_DRBG_C)
     17 
     18 #include "mbedtls/hmac_drbg.h"
     19 #include "mbedtls/platform_util.h"
     20 #include "mbedtls/error.h"
     21 
     22 #include <string.h>
     23 
     24 #if defined(MBEDTLS_FS_IO)
     25 #include <stdio.h>
     26 #endif
     27 
     28 #include "mbedtls/platform.h"
     29 
     30 /*
     31  * HMAC_DRBG context initialization
     32  */
     33 void mbedtls_hmac_drbg_init(mbedtls_hmac_drbg_context *ctx)
     34 {
     35     memset(ctx, 0, sizeof(mbedtls_hmac_drbg_context));
     36 
     37     ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
     38 }
     39 
     40 /*
     41  * HMAC_DRBG update, using optional additional data (10.1.2.2)
     42  */
     43 int mbedtls_hmac_drbg_update(mbedtls_hmac_drbg_context *ctx,
     44                              const unsigned char *additional,
     45                              size_t add_len)
     46 {
     47     size_t md_len = mbedtls_md_get_size(ctx->md_ctx.md_info);
     48     unsigned char rounds = (additional != NULL && add_len != 0) ? 2 : 1;
     49     unsigned char sep[1];
     50     unsigned char K[MBEDTLS_MD_MAX_SIZE];
     51     int ret = MBEDTLS_ERR_MD_BAD_INPUT_DATA;
     52 
     53     for (sep[0] = 0; sep[0] < rounds; sep[0]++) {
     54         /* Step 1 or 4 */
     55         if ((ret = mbedtls_md_hmac_reset(&ctx->md_ctx)) != 0) {
     56             goto exit;
     57         }
     58         if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,
     59                                           ctx->V, md_len)) != 0) {
     60             goto exit;
     61         }
     62         if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,
     63                                           sep, 1)) != 0) {
     64             goto exit;
     65         }
     66         if (rounds == 2) {
     67             if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,
     68                                               additional, add_len)) != 0) {
     69                 goto exit;
     70             }
     71         }
     72         if ((ret = mbedtls_md_hmac_finish(&ctx->md_ctx, K)) != 0) {
     73             goto exit;
     74         }
     75 
     76         /* Step 2 or 5 */
     77         if ((ret = mbedtls_md_hmac_starts(&ctx->md_ctx, K, md_len)) != 0) {
     78             goto exit;
     79         }
     80         if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,
     81                                           ctx->V, md_len)) != 0) {
     82             goto exit;
     83         }
     84         if ((ret = mbedtls_md_hmac_finish(&ctx->md_ctx, ctx->V)) != 0) {
     85             goto exit;
     86         }
     87     }
     88 
     89 exit:
     90     mbedtls_platform_zeroize(K, sizeof(K));
     91     return ret;
     92 }
     93 
     94 /*
     95  * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
     96  */
     97 int mbedtls_hmac_drbg_seed_buf(mbedtls_hmac_drbg_context *ctx,
     98                                const mbedtls_md_info_t *md_info,
     99                                const unsigned char *data, size_t data_len)
    100 {
    101     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    102 
    103     if ((ret = mbedtls_md_setup(&ctx->md_ctx, md_info, 1)) != 0) {
    104         return ret;
    105     }
    106 
    107 #if defined(MBEDTLS_THREADING_C)
    108     mbedtls_mutex_init(&ctx->mutex);
    109 #endif
    110 
    111     /*
    112      * Set initial working state.
    113      * Use the V memory location, which is currently all 0, to initialize the
    114      * MD context with an all-zero key. Then set V to its initial value.
    115      */
    116     if ((ret = mbedtls_md_hmac_starts(&ctx->md_ctx, ctx->V,
    117                                       mbedtls_md_get_size(md_info))) != 0) {
    118         return ret;
    119     }
    120     memset(ctx->V, 0x01, mbedtls_md_get_size(md_info));
    121 
    122     if ((ret = mbedtls_hmac_drbg_update(ctx, data, data_len)) != 0) {
    123         return ret;
    124     }
    125 
    126     return 0;
    127 }
    128 
    129 /*
    130  * Internal function used both for seeding and reseeding the DRBG.
    131  * Comments starting with arabic numbers refer to section 10.1.2.4
    132  * of SP800-90A, while roman numbers refer to section 9.2.
    133  */
    134 static int hmac_drbg_reseed_core(mbedtls_hmac_drbg_context *ctx,
    135                                  const unsigned char *additional, size_t len,
    136                                  int use_nonce)
    137 {
    138     unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
    139     size_t seedlen = 0;
    140     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    141 
    142     {
    143         size_t total_entropy_len;
    144 
    145         if (use_nonce == 0) {
    146             total_entropy_len = ctx->entropy_len;
    147         } else {
    148             total_entropy_len = ctx->entropy_len * 3 / 2;
    149         }
    150 
    151         /* III. Check input length */
    152         if (len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
    153             total_entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT) {
    154             return MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
    155         }
    156     }
    157 
    158     memset(seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT);
    159 
    160     /* IV. Gather entropy_len bytes of entropy for the seed */
    161     if ((ret = ctx->f_entropy(ctx->p_entropy,
    162                               seed, ctx->entropy_len)) != 0) {
    163         return MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED;
    164     }
    165     seedlen += ctx->entropy_len;
    166 
    167     /* For initial seeding, allow adding of nonce generated
    168      * from the entropy source. See Sect 8.6.7 in SP800-90A. */
    169     if (use_nonce) {
    170         /* Note: We don't merge the two calls to f_entropy() in order
    171          *       to avoid requesting too much entropy from f_entropy()
    172          *       at once. Specifically, if the underlying digest is not
    173          *       SHA-1, 3 / 2 * entropy_len is at least 36 Bytes, which
    174          *       is larger than the maximum of 32 Bytes that our own
    175          *       entropy source implementation can emit in a single
    176          *       call in configurations disabling SHA-512. */
    177         if ((ret = ctx->f_entropy(ctx->p_entropy,
    178                                   seed + seedlen,
    179                                   ctx->entropy_len / 2)) != 0) {
    180             return MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED;
    181         }
    182 
    183         seedlen += ctx->entropy_len / 2;
    184     }
    185 
    186 
    187     /* 1. Concatenate entropy and additional data if any */
    188     if (additional != NULL && len != 0) {
    189         memcpy(seed + seedlen, additional, len);
    190         seedlen += len;
    191     }
    192 
    193     /* 2. Update state */
    194     if ((ret = mbedtls_hmac_drbg_update(ctx, seed, seedlen)) != 0) {
    195         goto exit;
    196     }
    197 
    198     /* 3. Reset reseed_counter */
    199     ctx->reseed_counter = 1;
    200 
    201 exit:
    202     /* 4. Done */
    203     mbedtls_platform_zeroize(seed, seedlen);
    204     return ret;
    205 }
    206 
    207 /*
    208  * HMAC_DRBG reseeding: 10.1.2.4 + 9.2
    209  */
    210 int mbedtls_hmac_drbg_reseed(mbedtls_hmac_drbg_context *ctx,
    211                              const unsigned char *additional, size_t len)
    212 {
    213     return hmac_drbg_reseed_core(ctx, additional, len, 0);
    214 }
    215 
    216 /*
    217  * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
    218  *
    219  * The nonce is not passed as a separate parameter but extracted
    220  * from the entropy source as suggested in 8.6.7.
    221  */
    222 int mbedtls_hmac_drbg_seed(mbedtls_hmac_drbg_context *ctx,
    223                            const mbedtls_md_info_t *md_info,
    224                            int (*f_entropy)(void *, unsigned char *, size_t),
    225                            void *p_entropy,
    226                            const unsigned char *custom,
    227                            size_t len)
    228 {
    229     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    230     size_t md_size;
    231 
    232     if ((ret = mbedtls_md_setup(&ctx->md_ctx, md_info, 1)) != 0) {
    233         return ret;
    234     }
    235 
    236     /* The mutex is initialized iff the md context is set up. */
    237 #if defined(MBEDTLS_THREADING_C)
    238     mbedtls_mutex_init(&ctx->mutex);
    239 #endif
    240 
    241     md_size = mbedtls_md_get_size(md_info);
    242 
    243     /*
    244      * Set initial working state.
    245      * Use the V memory location, which is currently all 0, to initialize the
    246      * MD context with an all-zero key. Then set V to its initial value.
    247      */
    248     if ((ret = mbedtls_md_hmac_starts(&ctx->md_ctx, ctx->V, md_size)) != 0) {
    249         return ret;
    250     }
    251     memset(ctx->V, 0x01, md_size);
    252 
    253     ctx->f_entropy = f_entropy;
    254     ctx->p_entropy = p_entropy;
    255 
    256     if (ctx->entropy_len == 0) {
    257         /*
    258          * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
    259          * each hash function, then according to SP800-90A rev1 10.1 table 2,
    260          * min_entropy_len (in bits) is security_strength.
    261          *
    262          * (This also matches the sizes used in the NIST test vectors.)
    263          */
    264         ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
    265                            md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
    266                            32;  /* better (256+) -> 256 bits */
    267     }
    268 
    269     if ((ret = hmac_drbg_reseed_core(ctx, custom, len,
    270                                      1 /* add nonce */)) != 0) {
    271         return ret;
    272     }
    273 
    274     return 0;
    275 }
    276 
    277 /*
    278  * Set prediction resistance
    279  */
    280 void mbedtls_hmac_drbg_set_prediction_resistance(mbedtls_hmac_drbg_context *ctx,
    281                                                  int resistance)
    282 {
    283     ctx->prediction_resistance = resistance;
    284 }
    285 
    286 /*
    287  * Set entropy length grabbed for seeding
    288  */
    289 void mbedtls_hmac_drbg_set_entropy_len(mbedtls_hmac_drbg_context *ctx, size_t len)
    290 {
    291     ctx->entropy_len = len;
    292 }
    293 
    294 /*
    295  * Set reseed interval
    296  */
    297 void mbedtls_hmac_drbg_set_reseed_interval(mbedtls_hmac_drbg_context *ctx, int interval)
    298 {
    299     ctx->reseed_interval = interval;
    300 }
    301 
    302 /*
    303  * HMAC_DRBG random function with optional additional data:
    304  * 10.1.2.5 (arabic) + 9.3 (Roman)
    305  */
    306 int mbedtls_hmac_drbg_random_with_add(void *p_rng,
    307                                       unsigned char *output, size_t out_len,
    308                                       const unsigned char *additional, size_t add_len)
    309 {
    310     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    311     mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
    312     size_t md_len = mbedtls_md_get_size(ctx->md_ctx.md_info);
    313     size_t left = out_len;
    314     unsigned char *out = output;
    315 
    316     /* II. Check request length */
    317     if (out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST) {
    318         return MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG;
    319     }
    320 
    321     /* III. Check input length */
    322     if (add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT) {
    323         return MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
    324     }
    325 
    326     /* 1. (aka VII and IX) Check reseed counter and PR */
    327     if (ctx->f_entropy != NULL && /* For no-reseeding instances */
    328         (ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
    329          ctx->reseed_counter > ctx->reseed_interval)) {
    330         if ((ret = mbedtls_hmac_drbg_reseed(ctx, additional, add_len)) != 0) {
    331             return ret;
    332         }
    333 
    334         add_len = 0; /* VII.4 */
    335     }
    336 
    337     /* 2. Use additional data if any */
    338     if (additional != NULL && add_len != 0) {
    339         if ((ret = mbedtls_hmac_drbg_update(ctx,
    340                                             additional, add_len)) != 0) {
    341             goto exit;
    342         }
    343     }
    344 
    345     /* 3, 4, 5. Generate bytes */
    346     while (left != 0) {
    347         size_t use_len = left > md_len ? md_len : left;
    348 
    349         if ((ret = mbedtls_md_hmac_reset(&ctx->md_ctx)) != 0) {
    350             goto exit;
    351         }
    352         if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,
    353                                           ctx->V, md_len)) != 0) {
    354             goto exit;
    355         }
    356         if ((ret = mbedtls_md_hmac_finish(&ctx->md_ctx, ctx->V)) != 0) {
    357             goto exit;
    358         }
    359 
    360         memcpy(out, ctx->V, use_len);
    361         out += use_len;
    362         left -= use_len;
    363     }
    364 
    365     /* 6. Update */
    366     if ((ret = mbedtls_hmac_drbg_update(ctx,
    367                                         additional, add_len)) != 0) {
    368         goto exit;
    369     }
    370 
    371     /* 7. Update reseed counter */
    372     ctx->reseed_counter++;
    373 
    374 exit:
    375     /* 8. Done */
    376     return ret;
    377 }
    378 
    379 /*
    380  * HMAC_DRBG random function
    381  */
    382 int mbedtls_hmac_drbg_random(void *p_rng, unsigned char *output, size_t out_len)
    383 {
    384     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    385     mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
    386 
    387 #if defined(MBEDTLS_THREADING_C)
    388     if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
    389         return ret;
    390     }
    391 #endif
    392 
    393     ret = mbedtls_hmac_drbg_random_with_add(ctx, output, out_len, NULL, 0);
    394 
    395 #if defined(MBEDTLS_THREADING_C)
    396     if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
    397         return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
    398     }
    399 #endif
    400 
    401     return ret;
    402 }
    403 
    404 /*
    405  *  This function resets HMAC_DRBG context to the state immediately
    406  *  after initial call of mbedtls_hmac_drbg_init().
    407  */
    408 void mbedtls_hmac_drbg_free(mbedtls_hmac_drbg_context *ctx)
    409 {
    410     if (ctx == NULL) {
    411         return;
    412     }
    413 
    414 #if defined(MBEDTLS_THREADING_C)
    415     /* The mutex is initialized iff the md context is set up. */
    416     if (ctx->md_ctx.md_info != NULL) {
    417         mbedtls_mutex_free(&ctx->mutex);
    418     }
    419 #endif
    420     mbedtls_md_free(&ctx->md_ctx);
    421     mbedtls_platform_zeroize(ctx, sizeof(mbedtls_hmac_drbg_context));
    422     ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
    423 }
    424 
    425 #if defined(MBEDTLS_FS_IO)
    426 int mbedtls_hmac_drbg_write_seed_file(mbedtls_hmac_drbg_context *ctx, const char *path)
    427 {
    428     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    429     FILE *f;
    430     unsigned char buf[MBEDTLS_HMAC_DRBG_MAX_INPUT];
    431 
    432     if ((f = fopen(path, "wb")) == NULL) {
    433         return MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
    434     }
    435 
    436     /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
    437     mbedtls_setbuf(f, NULL);
    438 
    439     if ((ret = mbedtls_hmac_drbg_random(ctx, buf, sizeof(buf))) != 0) {
    440         goto exit;
    441     }
    442 
    443     if (fwrite(buf, 1, sizeof(buf), f) != sizeof(buf)) {
    444         ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
    445         goto exit;
    446     }
    447 
    448     ret = 0;
    449 
    450 exit:
    451     fclose(f);
    452     mbedtls_platform_zeroize(buf, sizeof(buf));
    453 
    454     return ret;
    455 }
    456 
    457 int mbedtls_hmac_drbg_update_seed_file(mbedtls_hmac_drbg_context *ctx, const char *path)
    458 {
    459     int ret = 0;
    460     FILE *f = NULL;
    461     size_t n;
    462     unsigned char buf[MBEDTLS_HMAC_DRBG_MAX_INPUT];
    463     unsigned char c;
    464 
    465     if ((f = fopen(path, "rb")) == NULL) {
    466         return MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
    467     }
    468 
    469     /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
    470     mbedtls_setbuf(f, NULL);
    471 
    472     n = fread(buf, 1, sizeof(buf), f);
    473     if (fread(&c, 1, 1, f) != 0) {
    474         ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
    475         goto exit;
    476     }
    477     if (n == 0 || ferror(f)) {
    478         ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
    479         goto exit;
    480     }
    481     fclose(f);
    482     f = NULL;
    483 
    484     ret = mbedtls_hmac_drbg_update(ctx, buf, n);
    485 
    486 exit:
    487     mbedtls_platform_zeroize(buf, sizeof(buf));
    488     if (f != NULL) {
    489         fclose(f);
    490     }
    491     if (ret != 0) {
    492         return ret;
    493     }
    494     return mbedtls_hmac_drbg_write_seed_file(ctx, path);
    495 }
    496 #endif /* MBEDTLS_FS_IO */
    497 
    498 
    499 #if defined(MBEDTLS_SELF_TEST)
    500 
    501 #if !defined(MBEDTLS_MD_CAN_SHA1)
    502 /* Dummy checkup routine */
    503 int mbedtls_hmac_drbg_self_test(int verbose)
    504 {
    505     (void) verbose;
    506     return 0;
    507 }
    508 #else
    509 
    510 #define OUTPUT_LEN  80
    511 
    512 /* From a NIST PR=true test vector */
    513 static const unsigned char entropy_pr[] = {
    514     0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
    515     0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
    516     0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
    517     0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
    518     0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4
    519 };
    520 static const unsigned char result_pr[OUTPUT_LEN] = {
    521     0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
    522     0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
    523     0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
    524     0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
    525     0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
    526     0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
    527     0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44
    528 };
    529 
    530 /* From a NIST PR=false test vector */
    531 static const unsigned char entropy_nopr[] = {
    532     0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
    533     0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
    534     0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
    535     0xe9, 0x9d, 0xfe, 0xdf
    536 };
    537 static const unsigned char result_nopr[OUTPUT_LEN] = {
    538     0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
    539     0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
    540     0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
    541     0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
    542     0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
    543     0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
    544     0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7
    545 };
    546 
    547 /* "Entropy" from buffer */
    548 static size_t test_offset;
    549 static int hmac_drbg_self_test_entropy(void *data,
    550                                        unsigned char *buf, size_t len)
    551 {
    552     const unsigned char *p = data;
    553     memcpy(buf, p + test_offset, len);
    554     test_offset += len;
    555     return 0;
    556 }
    557 
    558 #define CHK(c)    if ((c) != 0)                          \
    559     {                                       \
    560         if (verbose != 0)                  \
    561         mbedtls_printf("failed\n");  \
    562         return 1;                        \
    563     }
    564 
    565 /*
    566  * Checkup routine for HMAC_DRBG with SHA-1
    567  */
    568 int mbedtls_hmac_drbg_self_test(int verbose)
    569 {
    570     mbedtls_hmac_drbg_context ctx;
    571     unsigned char buf[OUTPUT_LEN];
    572     const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
    573 
    574     mbedtls_hmac_drbg_init(&ctx);
    575 
    576     /*
    577      * PR = True
    578      */
    579     if (verbose != 0) {
    580         mbedtls_printf("  HMAC_DRBG (PR = True) : ");
    581     }
    582 
    583     test_offset = 0;
    584     CHK(mbedtls_hmac_drbg_seed(&ctx, md_info,
    585                                hmac_drbg_self_test_entropy, (void *) entropy_pr,
    586                                NULL, 0));
    587     mbedtls_hmac_drbg_set_prediction_resistance(&ctx, MBEDTLS_HMAC_DRBG_PR_ON);
    588     CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));
    589     CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));
    590     CHK(memcmp(buf, result_pr, OUTPUT_LEN));
    591     mbedtls_hmac_drbg_free(&ctx);
    592 
    593     mbedtls_hmac_drbg_free(&ctx);
    594 
    595     if (verbose != 0) {
    596         mbedtls_printf("passed\n");
    597     }
    598 
    599     /*
    600      * PR = False
    601      */
    602     if (verbose != 0) {
    603         mbedtls_printf("  HMAC_DRBG (PR = False) : ");
    604     }
    605 
    606     mbedtls_hmac_drbg_init(&ctx);
    607 
    608     test_offset = 0;
    609     CHK(mbedtls_hmac_drbg_seed(&ctx, md_info,
    610                                hmac_drbg_self_test_entropy, (void *) entropy_nopr,
    611                                NULL, 0));
    612     CHK(mbedtls_hmac_drbg_reseed(&ctx, NULL, 0));
    613     CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));
    614     CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));
    615     CHK(memcmp(buf, result_nopr, OUTPUT_LEN));
    616     mbedtls_hmac_drbg_free(&ctx);
    617 
    618     mbedtls_hmac_drbg_free(&ctx);
    619 
    620     if (verbose != 0) {
    621         mbedtls_printf("passed\n");
    622     }
    623 
    624     if (verbose != 0) {
    625         mbedtls_printf("\n");
    626     }
    627 
    628     return 0;
    629 }
    630 #endif /* MBEDTLS_MD_CAN_SHA1 */
    631 #endif /* MBEDTLS_SELF_TEST */
    632 
    633 #endif /* MBEDTLS_HMAC_DRBG_C */