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