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