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