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