Coverage Report

Created: 2024-11-21 07:03

/src/mbedtls/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(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
/*
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
0
{
101
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
102
103
0
    if ((ret = mbedtls_md_setup(&ctx->md_ctx, md_info, 1)) != 0) {
104
0
        return ret;
105
0
    }
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
0
    if ((ret = mbedtls_md_hmac_starts(&ctx->md_ctx, ctx->V,
117
0
                                      mbedtls_md_get_size(md_info))) != 0) {
118
0
        return ret;
119
0
    }
120
0
    memset(ctx->V, 0x01, mbedtls_md_get_size(md_info));
121
122
0
    if ((ret = mbedtls_hmac_drbg_update(ctx, data, data_len)) != 0) {
123
0
        return ret;
124
0
    }
125
126
0
    return 0;
127
0
}
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
0
{
138
0
    unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
139
0
    size_t seedlen = 0;
140
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
141
142
0
    {
143
0
        size_t total_entropy_len;
144
145
0
        if (use_nonce == 0) {
146
0
            total_entropy_len = ctx->entropy_len;
147
0
        } else {
148
0
            total_entropy_len = ctx->entropy_len * 3 / 2;
149
0
        }
150
151
        /* III. Check input length */
152
0
        if (len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
153
0
            total_entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT) {
154
0
            return MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
155
0
        }
156
0
    }
157
158
0
    memset(seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT);
159
160
    /* IV. Gather entropy_len bytes of entropy for the seed */
161
0
    if ((ret = ctx->f_entropy(ctx->p_entropy,
162
0
                              seed, ctx->entropy_len)) != 0) {
163
0
        return MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED;
164
0
    }
165
0
    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
0
    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
0
        if ((ret = ctx->f_entropy(ctx->p_entropy,
178
0
                                  seed + seedlen,
179
0
                                  ctx->entropy_len / 2)) != 0) {
180
0
            return MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED;
181
0
        }
182
183
0
        seedlen += ctx->entropy_len / 2;
184
0
    }
185
186
187
    /* 1. Concatenate entropy and additional data if any */
188
0
    if (additional != NULL && len != 0) {
189
0
        memcpy(seed + seedlen, additional, len);
190
0
        seedlen += len;
191
0
    }
192
193
    /* 2. Update state */
194
0
    if ((ret = mbedtls_hmac_drbg_update(ctx, seed, seedlen)) != 0) {
195
0
        goto exit;
196
0
    }
197
198
    /* 3. Reset reseed_counter */
199
0
    ctx->reseed_counter = 1;
200
201
0
exit:
202
    /* 4. Done */
203
0
    mbedtls_platform_zeroize(seed, seedlen);
204
0
    return ret;
205
0
}
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
0
{
213
0
    return hmac_drbg_reseed_core(ctx, additional, len, 0);
214
0
}
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
0
{
229
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
230
0
    size_t md_size;
231
232
0
    if ((ret = mbedtls_md_setup(&ctx->md_ctx, md_info, 1)) != 0) {
233
0
        return ret;
234
0
    }
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
0
    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
0
    if ((ret = mbedtls_md_hmac_starts(&ctx->md_ctx, ctx->V, md_size)) != 0) {
249
0
        return ret;
250
0
    }
251
0
    memset(ctx->V, 0x01, md_size);
252
253
0
    ctx->f_entropy = f_entropy;
254
0
    ctx->p_entropy = p_entropy;
255
256
0
    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
0
        ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
265
0
                           md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
266
0
                           32;  /* better (256+) -> 256 bits */
267
0
    }
268
269
0
    if ((ret = hmac_drbg_reseed_core(ctx, custom, len,
270
0
                                     1 /* add nonce */)) != 0) {
271
0
        return ret;
272
0
    }
273
274
0
    return 0;
275
0
}
276
277
/*
278
 * Set prediction resistance
279
 */
280
void mbedtls_hmac_drbg_set_prediction_resistance(mbedtls_hmac_drbg_context *ctx,
281
                                                 int resistance)
282
0
{
283
0
    ctx->prediction_resistance = resistance;
284
0
}
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
0
{
291
0
    ctx->entropy_len = len;
292
0
}
293
294
/*
295
 * Set reseed interval
296
 */
297
void mbedtls_hmac_drbg_set_reseed_interval(mbedtls_hmac_drbg_context *ctx, int interval)
298
0
{
299
0
    ctx->reseed_interval = interval;
300
0
}
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
0
{
310
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
311
0
    mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
312
0
    size_t md_len = mbedtls_md_get_size(ctx->md_ctx.md_info);
313
0
    size_t left = out_len;
314
0
    unsigned char *out = output;
315
316
    /* II. Check request length */
317
0
    if (out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST) {
318
0
        return MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG;
319
0
    }
320
321
    /* III. Check input length */
322
0
    if (add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT) {
323
0
        return MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
324
0
    }
325
326
    /* 1. (aka VII and IX) Check reseed counter and PR */
327
0
    if (ctx->f_entropy != NULL && /* For no-reseeding instances */
328
0
        (ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
329
0
         ctx->reseed_counter > ctx->reseed_interval)) {
330
0
        if ((ret = mbedtls_hmac_drbg_reseed(ctx, additional, add_len)) != 0) {
331
0
            return ret;
332
0
        }
333
334
0
        add_len = 0; /* VII.4 */
335
0
    }
336
337
    /* 2. Use additional data if any */
338
0
    if (additional != NULL && add_len != 0) {
339
0
        if ((ret = mbedtls_hmac_drbg_update(ctx,
340
0
                                            additional, add_len)) != 0) {
341
0
            goto exit;
342
0
        }
343
0
    }
344
345
    /* 3, 4, 5. Generate bytes */
346
0
    while (left != 0) {
347
0
        size_t use_len = left > md_len ? md_len : left;
348
349
0
        if ((ret = mbedtls_md_hmac_reset(&ctx->md_ctx)) != 0) {
350
0
            goto exit;
351
0
        }
352
0
        if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,
353
0
                                          ctx->V, md_len)) != 0) {
354
0
            goto exit;
355
0
        }
356
0
        if ((ret = mbedtls_md_hmac_finish(&ctx->md_ctx, ctx->V)) != 0) {
357
0
            goto exit;
358
0
        }
359
360
0
        memcpy(out, ctx->V, use_len);
361
0
        out += use_len;
362
0
        left -= use_len;
363
0
    }
364
365
    /* 6. Update */
366
0
    if ((ret = mbedtls_hmac_drbg_update(ctx,
367
0
                                        additional, add_len)) != 0) {
368
0
        goto exit;
369
0
    }
370
371
    /* 7. Update reseed counter */
372
0
    ctx->reseed_counter++;
373
374
0
exit:
375
    /* 8. Done */
376
0
    return ret;
377
0
}
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
0
{
384
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
385
0
    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
0
    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
0
    return ret;
402
0
}
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
0
{
410
0
    if (ctx == NULL) {
411
0
        return;
412
0
    }
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
0
    mbedtls_md_free(&ctx->md_ctx);
421
0
    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_hmac_drbg_context));
422
0
    ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
423
0
}
424
425
#if defined(MBEDTLS_FS_IO)
426
int mbedtls_hmac_drbg_write_seed_file(mbedtls_hmac_drbg_context *ctx, const char *path)
427
0
{
428
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
429
0
    FILE *f;
430
0
    unsigned char buf[MBEDTLS_HMAC_DRBG_MAX_INPUT];
431
432
0
    if ((f = fopen(path, "wb")) == NULL) {
433
0
        return MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
434
0
    }
435
436
    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
437
0
    mbedtls_setbuf(f, NULL);
438
439
0
    if ((ret = mbedtls_hmac_drbg_random(ctx, buf, sizeof(buf))) != 0) {
440
0
        goto exit;
441
0
    }
442
443
0
    if (fwrite(buf, 1, sizeof(buf), f) != sizeof(buf)) {
444
0
        ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
445
0
        goto exit;
446
0
    }
447
448
0
    ret = 0;
449
450
0
exit:
451
0
    fclose(f);
452
0
    mbedtls_platform_zeroize(buf, sizeof(buf));
453
454
0
    return ret;
455
0
}
456
457
int mbedtls_hmac_drbg_update_seed_file(mbedtls_hmac_drbg_context *ctx, const char *path)
458
0
{
459
0
    int ret = 0;
460
0
    FILE *f = NULL;
461
0
    size_t n;
462
0
    unsigned char buf[MBEDTLS_HMAC_DRBG_MAX_INPUT];
463
0
    unsigned char c;
464
465
0
    if ((f = fopen(path, "rb")) == NULL) {
466
0
        return MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
467
0
    }
468
469
    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
470
0
    mbedtls_setbuf(f, NULL);
471
472
0
    n = fread(buf, 1, sizeof(buf), f);
473
0
    if (fread(&c, 1, 1, f) != 0) {
474
0
        ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
475
0
        goto exit;
476
0
    }
477
0
    if (n == 0 || ferror(f)) {
478
0
        ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
479
0
        goto exit;
480
0
    }
481
0
    fclose(f);
482
0
    f = NULL;
483
484
0
    ret = mbedtls_hmac_drbg_update(ctx, buf, n);
485
486
0
exit:
487
0
    mbedtls_platform_zeroize(buf, sizeof(buf));
488
0
    if (f != NULL) {
489
0
        fclose(f);
490
0
    }
491
0
    if (ret != 0) {
492
0
        return ret;
493
0
    }
494
0
    return mbedtls_hmac_drbg_write_seed_file(ctx, path);
495
0
}
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
0
{
552
0
    const unsigned char *p = data;
553
0
    memcpy(buf, p + test_offset, len);
554
0
    test_offset += len;
555
0
    return 0;
556
0
}
557
558
0
#define CHK(c)    if ((c) != 0)                          \
559
0
    {                                       \
560
0
        if (verbose != 0)                  \
561
0
        mbedtls_printf("failed\n");  \
562
0
        return 1;                        \
563
0
    }
564
565
/*
566
 * Checkup routine for HMAC_DRBG with SHA-1
567
 */
568
int mbedtls_hmac_drbg_self_test(int verbose)
569
0
{
570
0
    mbedtls_hmac_drbg_context ctx;
571
0
    unsigned char buf[OUTPUT_LEN];
572
0
    const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
573
574
0
    mbedtls_hmac_drbg_init(&ctx);
575
576
    /*
577
     * PR = True
578
     */
579
0
    if (verbose != 0) {
580
0
        mbedtls_printf("  HMAC_DRBG (PR = True) : ");
581
0
    }
582
583
0
    test_offset = 0;
584
0
    CHK(mbedtls_hmac_drbg_seed(&ctx, md_info,
585
0
                               hmac_drbg_self_test_entropy, (void *) entropy_pr,
586
0
                               NULL, 0));
587
0
    mbedtls_hmac_drbg_set_prediction_resistance(&ctx, MBEDTLS_HMAC_DRBG_PR_ON);
588
0
    CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));
589
0
    CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));
590
0
    CHK(memcmp(buf, result_pr, OUTPUT_LEN));
591
0
    mbedtls_hmac_drbg_free(&ctx);
592
593
0
    mbedtls_hmac_drbg_free(&ctx);
594
595
0
    if (verbose != 0) {
596
0
        mbedtls_printf("passed\n");
597
0
    }
598
599
    /*
600
     * PR = False
601
     */
602
0
    if (verbose != 0) {
603
0
        mbedtls_printf("  HMAC_DRBG (PR = False) : ");
604
0
    }
605
606
0
    mbedtls_hmac_drbg_init(&ctx);
607
608
0
    test_offset = 0;
609
0
    CHK(mbedtls_hmac_drbg_seed(&ctx, md_info,
610
0
                               hmac_drbg_self_test_entropy, (void *) entropy_nopr,
611
0
                               NULL, 0));
612
0
    CHK(mbedtls_hmac_drbg_reseed(&ctx, NULL, 0));
613
0
    CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));
614
0
    CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));
615
0
    CHK(memcmp(buf, result_nopr, OUTPUT_LEN));
616
0
    mbedtls_hmac_drbg_free(&ctx);
617
618
0
    mbedtls_hmac_drbg_free(&ctx);
619
620
0
    if (verbose != 0) {
621
0
        mbedtls_printf("passed\n");
622
0
    }
623
624
0
    if (verbose != 0) {
625
0
        mbedtls_printf("\n");
626
0
    }
627
628
0
    return 0;
629
0
}
630
#endif /* MBEDTLS_MD_CAN_SHA1 */
631
#endif /* MBEDTLS_SELF_TEST */
632
633
#endif /* MBEDTLS_HMAC_DRBG_C */