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