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  */
mbedtls_hmac_drbg_init(mbedtls_hmac_drbg_context * ctx)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  */
mbedtls_hmac_drbg_update(mbedtls_hmac_drbg_context * ctx,const unsigned char * additional,size_t add_len)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  */
mbedtls_hmac_drbg_seed_buf(mbedtls_hmac_drbg_context * ctx,const mbedtls_md_info_t * md_info,const unsigned char * data,size_t data_len)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  */
hmac_drbg_reseed_core(mbedtls_hmac_drbg_context * ctx,const unsigned char * additional,size_t len,int use_nonce)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  */
mbedtls_hmac_drbg_reseed(mbedtls_hmac_drbg_context * ctx,const unsigned char * additional,size_t len)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  */
mbedtls_hmac_drbg_seed(mbedtls_hmac_drbg_context * ctx,const mbedtls_md_info_t * md_info,int (* f_entropy)(void *,unsigned char *,size_t),void * p_entropy,const unsigned char * custom,size_t len)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  */
mbedtls_hmac_drbg_set_prediction_resistance(mbedtls_hmac_drbg_context * ctx,int resistance)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  */
mbedtls_hmac_drbg_set_entropy_len(mbedtls_hmac_drbg_context * ctx,size_t len)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  */
mbedtls_hmac_drbg_set_reseed_interval(mbedtls_hmac_drbg_context * ctx,int interval)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  */
mbedtls_hmac_drbg_random_with_add(void * p_rng,unsigned char * output,size_t out_len,const unsigned char * additional,size_t add_len)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  */
mbedtls_hmac_drbg_random(void * p_rng,unsigned char * output,size_t out_len)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  */
mbedtls_hmac_drbg_free(mbedtls_hmac_drbg_context * ctx)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)
mbedtls_hmac_drbg_write_seed_file(mbedtls_hmac_drbg_context * ctx,const char * path)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 
mbedtls_hmac_drbg_update_seed_file(mbedtls_hmac_drbg_context * ctx,const char * path)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 */
mbedtls_hmac_drbg_self_test(int verbose)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;
hmac_drbg_self_test_entropy(void * data,unsigned char * buf,size_t len)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  */
mbedtls_hmac_drbg_self_test(int verbose)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 */
634