• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_ret(mbedtls_hmac_drbg_context * ctx,const unsigned char * additional,size_t add_len)43 int mbedtls_hmac_drbg_update_ret(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 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
mbedtls_hmac_drbg_update(mbedtls_hmac_drbg_context * ctx,const unsigned char * additional,size_t add_len)95 void mbedtls_hmac_drbg_update(mbedtls_hmac_drbg_context *ctx,
96                               const unsigned char *additional,
97                               size_t add_len)
98 {
99     (void) mbedtls_hmac_drbg_update_ret(ctx, additional, add_len);
100 }
101 #endif /* MBEDTLS_DEPRECATED_REMOVED */
102 
103 /*
104  * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
105  */
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)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 {
110     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
111 
112     if ((ret = mbedtls_md_setup(&ctx->md_ctx, md_info, 1)) != 0) {
113         return ret;
114     }
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     if ((ret = mbedtls_md_hmac_starts(&ctx->md_ctx, ctx->V,
126                                       mbedtls_md_get_size(md_info))) != 0) {
127         return ret;
128     }
129     memset(ctx->V, 0x01, mbedtls_md_get_size(md_info));
130 
131     if ((ret = mbedtls_hmac_drbg_update_ret(ctx, data, data_len)) != 0) {
132         return ret;
133     }
134 
135     return 0;
136 }
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  */
hmac_drbg_reseed_core(mbedtls_hmac_drbg_context * ctx,const unsigned char * additional,size_t len,int use_nonce)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 {
147     unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
148     size_t seedlen = 0;
149     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
150 
151     {
152         size_t total_entropy_len;
153 
154         if (use_nonce == 0) {
155             total_entropy_len = ctx->entropy_len;
156         } else {
157             total_entropy_len = ctx->entropy_len * 3 / 2;
158         }
159 
160         /* III. Check input length */
161         if (len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
162             total_entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT) {
163             return MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
164         }
165     }
166 
167     memset(seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT);
168 
169     /* IV. Gather entropy_len bytes of entropy for the seed */
170     if ((ret = ctx->f_entropy(ctx->p_entropy,
171                               seed, ctx->entropy_len)) != 0) {
172         return MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED;
173     }
174     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     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         if ((ret = ctx->f_entropy(ctx->p_entropy,
187                                   seed + seedlen,
188                                   ctx->entropy_len / 2)) != 0) {
189             return MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED;
190         }
191 
192         seedlen += ctx->entropy_len / 2;
193     }
194 
195 
196     /* 1. Concatenate entropy and additional data if any */
197     if (additional != NULL && len != 0) {
198         memcpy(seed + seedlen, additional, len);
199         seedlen += len;
200     }
201 
202     /* 2. Update state */
203     if ((ret = mbedtls_hmac_drbg_update_ret(ctx, seed, seedlen)) != 0) {
204         goto exit;
205     }
206 
207     /* 3. Reset reseed_counter */
208     ctx->reseed_counter = 1;
209 
210 exit:
211     /* 4. Done */
212     mbedtls_platform_zeroize(seed, seedlen);
213     return ret;
214 }
215 
216 /*
217  * HMAC_DRBG reseeding: 10.1.2.4 + 9.2
218  */
mbedtls_hmac_drbg_reseed(mbedtls_hmac_drbg_context * ctx,const unsigned char * additional,size_t len)219 int mbedtls_hmac_drbg_reseed(mbedtls_hmac_drbg_context *ctx,
220                              const unsigned char *additional, size_t len)
221 {
222     return hmac_drbg_reseed_core(ctx, additional, len, 0);
223 }
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  */
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)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 {
238     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
239     size_t md_size;
240 
241     if ((ret = mbedtls_md_setup(&ctx->md_ctx, md_info, 1)) != 0) {
242         return ret;
243     }
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     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     if ((ret = mbedtls_md_hmac_starts(&ctx->md_ctx, ctx->V, md_size)) != 0) {
258         return ret;
259     }
260     memset(ctx->V, 0x01, md_size);
261 
262     ctx->f_entropy = f_entropy;
263     ctx->p_entropy = p_entropy;
264 
265     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         ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
274                            md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
275                            32;  /* better (256+) -> 256 bits */
276     }
277 
278     if ((ret = hmac_drbg_reseed_core(ctx, custom, len,
279                                      1 /* add nonce */)) != 0) {
280         return ret;
281     }
282 
283     return 0;
284 }
285 
286 /*
287  * Set prediction resistance
288  */
mbedtls_hmac_drbg_set_prediction_resistance(mbedtls_hmac_drbg_context * ctx,int resistance)289 void mbedtls_hmac_drbg_set_prediction_resistance(mbedtls_hmac_drbg_context *ctx,
290                                                  int resistance)
291 {
292     ctx->prediction_resistance = resistance;
293 }
294 
295 /*
296  * Set entropy length grabbed for seeding
297  */
mbedtls_hmac_drbg_set_entropy_len(mbedtls_hmac_drbg_context * ctx,size_t len)298 void mbedtls_hmac_drbg_set_entropy_len(mbedtls_hmac_drbg_context *ctx, size_t len)
299 {
300     ctx->entropy_len = len;
301 }
302 
303 /*
304  * Set reseed interval
305  */
mbedtls_hmac_drbg_set_reseed_interval(mbedtls_hmac_drbg_context * ctx,int interval)306 void mbedtls_hmac_drbg_set_reseed_interval(mbedtls_hmac_drbg_context *ctx, int interval)
307 {
308     ctx->reseed_interval = interval;
309 }
310 
311 /*
312  * HMAC_DRBG random function with optional additional data:
313  * 10.1.2.5 (arabic) + 9.3 (Roman)
314  */
mbedtls_hmac_drbg_random_with_add(void * p_rng,unsigned char * output,size_t out_len,const unsigned char * additional,size_t add_len)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 {
319     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
320     mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
321     size_t md_len = mbedtls_md_get_size(ctx->md_ctx.md_info);
322     size_t left = out_len;
323     unsigned char *out = output;
324 
325     /* II. Check request length */
326     if (out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST) {
327         return MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG;
328     }
329 
330     /* III. Check input length */
331     if (add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT) {
332         return MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
333     }
334 
335     /* 1. (aka VII and IX) Check reseed counter and PR */
336     if (ctx->f_entropy != NULL && /* For no-reseeding instances */
337         (ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
338          ctx->reseed_counter > ctx->reseed_interval)) {
339         if ((ret = mbedtls_hmac_drbg_reseed(ctx, additional, add_len)) != 0) {
340             return ret;
341         }
342 
343         add_len = 0; /* VII.4 */
344     }
345 
346     /* 2. Use additional data if any */
347     if (additional != NULL && add_len != 0) {
348         if ((ret = mbedtls_hmac_drbg_update_ret(ctx,
349                                                 additional, add_len)) != 0) {
350             goto exit;
351         }
352     }
353 
354     /* 3, 4, 5. Generate bytes */
355     while (left != 0) {
356         size_t use_len = left > md_len ? md_len : left;
357 
358         if ((ret = mbedtls_md_hmac_reset(&ctx->md_ctx)) != 0) {
359             goto exit;
360         }
361         if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,
362                                           ctx->V, md_len)) != 0) {
363             goto exit;
364         }
365         if ((ret = mbedtls_md_hmac_finish(&ctx->md_ctx, ctx->V)) != 0) {
366             goto exit;
367         }
368 
369         memcpy(out, ctx->V, use_len);
370         out += use_len;
371         left -= use_len;
372     }
373 
374     /* 6. Update */
375     if ((ret = mbedtls_hmac_drbg_update_ret(ctx,
376                                             additional, add_len)) != 0) {
377         goto exit;
378     }
379 
380     /* 7. Update reseed counter */
381     ctx->reseed_counter++;
382 
383 exit:
384     /* 8. Done */
385     return ret;
386 }
387 
388 /*
389  * HMAC_DRBG random function
390  */
mbedtls_hmac_drbg_random(void * p_rng,unsigned char * output,size_t out_len)391 int mbedtls_hmac_drbg_random(void *p_rng, unsigned char *output, size_t out_len)
392 {
393     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
394     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     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     return ret;
411 }
412 
413 /*
414  *  This function resets HMAC_DRBG context to the state immediately
415  *  after initial call of mbedtls_hmac_drbg_init().
416  */
mbedtls_hmac_drbg_free(mbedtls_hmac_drbg_context * ctx)417 void mbedtls_hmac_drbg_free(mbedtls_hmac_drbg_context *ctx)
418 {
419     if (ctx == NULL) {
420         return;
421     }
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     mbedtls_md_free(&ctx->md_ctx);
430     mbedtls_platform_zeroize(ctx, sizeof(mbedtls_hmac_drbg_context));
431     ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
432 }
433 
434 #if defined(MBEDTLS_FS_IO)
mbedtls_hmac_drbg_write_seed_file(mbedtls_hmac_drbg_context * ctx,const char * path)435 int mbedtls_hmac_drbg_write_seed_file(mbedtls_hmac_drbg_context *ctx, const char *path)
436 {
437     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
438     FILE *f;
439     unsigned char buf[MBEDTLS_HMAC_DRBG_MAX_INPUT];
440 
441     if ((f = fopen(path, "wb")) == NULL) {
442         return MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
443     }
444 
445     if ((ret = mbedtls_hmac_drbg_random(ctx, buf, sizeof(buf))) != 0) {
446         goto exit;
447     }
448 
449     if (fwrite(buf, 1, sizeof(buf), f) != sizeof(buf)) {
450         ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
451         goto exit;
452     }
453 
454     ret = 0;
455 
456 exit:
457     fclose(f);
458     mbedtls_platform_zeroize(buf, sizeof(buf));
459 
460     return ret;
461 }
462 
mbedtls_hmac_drbg_update_seed_file(mbedtls_hmac_drbg_context * ctx,const char * path)463 int mbedtls_hmac_drbg_update_seed_file(mbedtls_hmac_drbg_context *ctx, const char *path)
464 {
465     int ret = 0;
466     FILE *f = NULL;
467     size_t n;
468     unsigned char buf[MBEDTLS_HMAC_DRBG_MAX_INPUT];
469     unsigned char c;
470 
471     if ((f = fopen(path, "rb")) == NULL) {
472         return MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
473     }
474 
475     n = fread(buf, 1, sizeof(buf), f);
476     if (fread(&c, 1, 1, f) != 0) {
477         ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
478         goto exit;
479     }
480     if (n == 0 || ferror(f)) {
481         ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
482         goto exit;
483     }
484     fclose(f);
485     f = NULL;
486 
487     ret = mbedtls_hmac_drbg_update_ret(ctx, buf, n);
488 
489 exit:
490     mbedtls_platform_zeroize(buf, sizeof(buf));
491     if (f != NULL) {
492         fclose(f);
493     }
494     if (ret != 0) {
495         return ret;
496     }
497     return mbedtls_hmac_drbg_write_seed_file(ctx, path);
498 }
499 #endif /* MBEDTLS_FS_IO */
500 
501 
502 #if defined(MBEDTLS_SELF_TEST)
503 
504 #if !defined(MBEDTLS_SHA1_C)
505 /* Dummy checkup routine */
mbedtls_hmac_drbg_self_test(int verbose)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;
hmac_drbg_self_test_entropy(void * data,unsigned char * buf,size_t len)552 static int hmac_drbg_self_test_entropy(void *data,
553                                        unsigned char *buf, size_t len)
554 {
555     const unsigned char *p = data;
556     memcpy(buf, p + test_offset, len);
557     test_offset += len;
558     return 0;
559 }
560 
561 #define CHK(c)    if ((c) != 0)                          \
562     {                                       \
563         if (verbose != 0)                  \
564         mbedtls_printf("failed\n");  \
565         return 1;                        \
566     }
567 
568 /*
569  * Checkup routine for HMAC_DRBG with SHA-1
570  */
mbedtls_hmac_drbg_self_test(int verbose)571 int mbedtls_hmac_drbg_self_test(int verbose)
572 {
573     mbedtls_hmac_drbg_context ctx;
574     unsigned char buf[OUTPUT_LEN];
575     const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
576 
577     mbedtls_hmac_drbg_init(&ctx);
578 
579     /*
580      * PR = True
581      */
582     if (verbose != 0) {
583         mbedtls_printf("  HMAC_DRBG (PR = True) : ");
584     }
585 
586     test_offset = 0;
587     CHK(mbedtls_hmac_drbg_seed(&ctx, md_info,
588                                hmac_drbg_self_test_entropy, (void *) entropy_pr,
589                                NULL, 0));
590     mbedtls_hmac_drbg_set_prediction_resistance(&ctx, MBEDTLS_HMAC_DRBG_PR_ON);
591     CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));
592     CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));
593     CHK(memcmp(buf, result_pr, OUTPUT_LEN));
594     mbedtls_hmac_drbg_free(&ctx);
595 
596     mbedtls_hmac_drbg_free(&ctx);
597 
598     if (verbose != 0) {
599         mbedtls_printf("passed\n");
600     }
601 
602     /*
603      * PR = False
604      */
605     if (verbose != 0) {
606         mbedtls_printf("  HMAC_DRBG (PR = False) : ");
607     }
608 
609     mbedtls_hmac_drbg_init(&ctx);
610 
611     test_offset = 0;
612     CHK(mbedtls_hmac_drbg_seed(&ctx, md_info,
613                                hmac_drbg_self_test_entropy, (void *) entropy_nopr,
614                                NULL, 0));
615     CHK(mbedtls_hmac_drbg_reseed(&ctx, NULL, 0));
616     CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));
617     CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));
618     CHK(memcmp(buf, result_nopr, OUTPUT_LEN));
619     mbedtls_hmac_drbg_free(&ctx);
620 
621     mbedtls_hmac_drbg_free(&ctx);
622 
623     if (verbose != 0) {
624         mbedtls_printf("passed\n");
625     }
626 
627     if (verbose != 0) {
628         mbedtls_printf("\n");
629     }
630 
631     return 0;
632 }
633 #endif /* MBEDTLS_SHA1_C */
634 #endif /* MBEDTLS_SELF_TEST */
635 
636 #endif /* MBEDTLS_HMAC_DRBG_C */
637