Coverage Report

Created: 2025-07-01 06:54

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