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 #if defined(MBEDTLS_SELF_TEST)
41 #if defined(MBEDTLS_PLATFORM_C)
42 #include "mbedtls/platform.h"
43 #else
44 #include <stdio.h>
45 #define mbedtls_printf printf
46 #endif /* MBEDTLS_SELF_TEST */
47 #endif /* MBEDTLS_PLATFORM_C */
48
49 /*
50 * HMAC_DRBG context initialization
51 */
mbedtls_hmac_drbg_init(mbedtls_hmac_drbg_context * ctx)52 void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx )
53 {
54 memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) );
55
56 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
57 }
58
59 /*
60 * HMAC_DRBG update, using optional additional data (10.1.2.2)
61 */
mbedtls_hmac_drbg_update(mbedtls_hmac_drbg_context * ctx,const unsigned char * additional,size_t add_len)62 int mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
63 const unsigned char *additional,
64 size_t add_len )
65 {
66 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
67 unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
68 unsigned char sep[1];
69 unsigned char K[MBEDTLS_MD_MAX_SIZE];
70 int ret = MBEDTLS_ERR_MD_BAD_INPUT_DATA;
71
72 for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
73 {
74 /* Step 1 or 4 */
75 if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
76 goto exit;
77 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
78 ctx->V, md_len ) ) != 0 )
79 goto exit;
80 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
81 sep, 1 ) ) != 0 )
82 goto exit;
83 if( rounds == 2 )
84 {
85 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
86 additional, add_len ) ) != 0 )
87 goto exit;
88 }
89 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, K ) ) != 0 )
90 goto exit;
91
92 /* Step 2 or 5 */
93 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ) ) != 0 )
94 goto exit;
95 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
96 ctx->V, md_len ) ) != 0 )
97 goto exit;
98 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
99 goto exit;
100 }
101
102 exit:
103 mbedtls_platform_zeroize( K, sizeof( K ) );
104 return( ret );
105 }
106
107 /*
108 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
109 */
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)110 int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
111 const mbedtls_md_info_t * md_info,
112 const unsigned char *data, size_t data_len )
113 {
114 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
115
116 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
117 return( ret );
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 memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) );
132
133 if( ( ret = mbedtls_hmac_drbg_update( ctx, data, data_len ) ) != 0 )
134 return( ret );
135
136 return( 0 );
137 }
138
139 /*
140 * Internal function used both for seeding and reseeding the DRBG.
141 * Comments starting with arabic numbers refer to section 10.1.2.4
142 * of SP800-90A, while roman numbers refer to section 9.2.
143 */
hmac_drbg_reseed_core(mbedtls_hmac_drbg_context * ctx,const unsigned char * additional,size_t len,int use_nonce)144 static int hmac_drbg_reseed_core( mbedtls_hmac_drbg_context *ctx,
145 const unsigned char *additional, size_t len,
146 int use_nonce )
147 {
148 unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
149 size_t seedlen = 0;
150 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
151
152 {
153 size_t total_entropy_len;
154
155 if( use_nonce == 0 )
156 total_entropy_len = ctx->entropy_len;
157 else
158 total_entropy_len = ctx->entropy_len * 3 / 2;
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 {
164 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
165 }
166 }
167
168 memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
169
170 /* IV. Gather entropy_len bytes of entropy for the seed */
171 if( ( ret = ctx->f_entropy( ctx->p_entropy,
172 seed, ctx->entropy_len ) ) != 0 )
173 {
174 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
175 }
176 seedlen += ctx->entropy_len;
177
178 /* For initial seeding, allow adding of nonce generated
179 * from the entropy source. See Sect 8.6.7 in SP800-90A. */
180 if( use_nonce )
181 {
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 {
193 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
194 }
195
196 seedlen += ctx->entropy_len / 2;
197 }
198
199
200 /* 1. Concatenate entropy and additional data if any */
201 if( additional != NULL && len != 0 )
202 {
203 memcpy( seed + seedlen, additional, len );
204 seedlen += len;
205 }
206
207 /* 2. Update state */
208 if( ( ret = mbedtls_hmac_drbg_update( ctx, seed, seedlen ) ) != 0 )
209 goto exit;
210
211 /* 3. Reset reseed_counter */
212 ctx->reseed_counter = 1;
213
214 exit:
215 /* 4. Done */
216 mbedtls_platform_zeroize( seed, seedlen );
217 return( ret );
218 }
219
220 /*
221 * HMAC_DRBG reseeding: 10.1.2.4 + 9.2
222 */
mbedtls_hmac_drbg_reseed(mbedtls_hmac_drbg_context * ctx,const unsigned char * additional,size_t len)223 int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
224 const unsigned char *additional, size_t len )
225 {
226 return( hmac_drbg_reseed_core( ctx, additional, len, 0 ) );
227 }
228
229 /*
230 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
231 *
232 * The nonce is not passed as a separate parameter but extracted
233 * from the entropy source as suggested in 8.6.7.
234 */
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)235 int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
236 const mbedtls_md_info_t * md_info,
237 int (*f_entropy)(void *, unsigned char *, size_t),
238 void *p_entropy,
239 const unsigned char *custom,
240 size_t len )
241 {
242 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
243 size_t md_size;
244
245 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
246 return( ret );
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 memset( ctx->V, 0x01, md_size );
263
264 ctx->f_entropy = f_entropy;
265 ctx->p_entropy = p_entropy;
266
267 if( ctx->entropy_len == 0 )
268 {
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 {
284 return( ret );
285 }
286
287 return( 0 );
288 }
289
290 /*
291 * Set prediction resistance
292 */
mbedtls_hmac_drbg_set_prediction_resistance(mbedtls_hmac_drbg_context * ctx,int resistance)293 void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
294 int resistance )
295 {
296 ctx->prediction_resistance = resistance;
297 }
298
299 /*
300 * Set entropy length grabbed for seeding
301 */
mbedtls_hmac_drbg_set_entropy_len(mbedtls_hmac_drbg_context * ctx,size_t len)302 void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
303 {
304 ctx->entropy_len = len;
305 }
306
307 /*
308 * Set reseed interval
309 */
mbedtls_hmac_drbg_set_reseed_interval(mbedtls_hmac_drbg_context * ctx,int interval)310 void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval )
311 {
312 ctx->reseed_interval = interval;
313 }
314
315 /*
316 * HMAC_DRBG random function with optional additional data:
317 * 10.1.2.5 (arabic) + 9.3 (Roman)
318 */
mbedtls_hmac_drbg_random_with_add(void * p_rng,unsigned char * output,size_t out_len,const unsigned char * additional,size_t add_len)319 int mbedtls_hmac_drbg_random_with_add( void *p_rng,
320 unsigned char *output, size_t out_len,
321 const unsigned char *additional, size_t add_len )
322 {
323 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
324 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
325 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
326 size_t left = out_len;
327 unsigned char *out = output;
328
329 /* II. Check request length */
330 if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST )
331 return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
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 /* 1. (aka VII and IX) Check reseed counter and PR */
338 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
339 ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
340 ctx->reseed_counter > ctx->reseed_interval ) )
341 {
342 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
343 return( ret );
344
345 add_len = 0; /* VII.4 */
346 }
347
348 /* 2. Use additional data if any */
349 if( additional != NULL && add_len != 0 )
350 {
351 if( ( ret = mbedtls_hmac_drbg_update( ctx,
352 additional, add_len ) ) != 0 )
353 goto exit;
354 }
355
356 /* 3, 4, 5. Generate bytes */
357 while( left != 0 )
358 {
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 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
364 ctx->V, md_len ) ) != 0 )
365 goto exit;
366 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
367 goto exit;
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( ctx,
376 additional, add_len ) ) != 0 )
377 goto exit;
378
379 /* 7. Update reseed counter */
380 ctx->reseed_counter++;
381
382 exit:
383 /* 8. Done */
384 return( ret );
385 }
386
387 /*
388 * HMAC_DRBG random function
389 */
mbedtls_hmac_drbg_random(void * p_rng,unsigned char * output,size_t out_len)390 int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
391 {
392 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
393 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
394
395 #if defined(MBEDTLS_THREADING_C)
396 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
397 return( ret );
398 #endif
399
400 ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
401
402 #if defined(MBEDTLS_THREADING_C)
403 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
404 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
405 #endif
406
407 return( ret );
408 }
409
410 /*
411 * This function resets HMAC_DRBG context to the state immediately
412 * after initial call of mbedtls_hmac_drbg_init().
413 */
mbedtls_hmac_drbg_free(mbedtls_hmac_drbg_context * ctx)414 void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
415 {
416 if( ctx == NULL )
417 return;
418
419 #if defined(MBEDTLS_THREADING_C)
420 /* The mutex is initialized iff the md context is set up. */
421 if( ctx->md_ctx.md_info != NULL )
422 mbedtls_mutex_free( &ctx->mutex );
423 #endif
424 mbedtls_md_free( &ctx->md_ctx );
425 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
426 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
427 }
428
429 #if defined(MBEDTLS_FS_IO)
mbedtls_hmac_drbg_write_seed_file(mbedtls_hmac_drbg_context * ctx,const char * path)430 int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
431 {
432 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
433 FILE *f;
434 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
435
436 if( ( f = fopen( path, "wb" ) ) == NULL )
437 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
438
439 if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
440 goto exit;
441
442 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
443 {
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 n = fread( buf, 1, sizeof( buf ), f );
469 if( fread( &c, 1, 1, f ) != 0 )
470 {
471 ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
472 goto exit;
473 }
474 if( n == 0 || ferror( f ) )
475 {
476 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
477 goto exit;
478 }
479 fclose( f );
480 f = NULL;
481
482 ret = mbedtls_hmac_drbg_update( ctx, buf, n );
483
484 exit:
485 mbedtls_platform_zeroize( buf, sizeof( buf ) );
486 if( f != NULL )
487 fclose( f );
488 if( ret != 0 )
489 return( ret );
490 return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
491 }
492 #endif /* MBEDTLS_FS_IO */
493
494
495 #if defined(MBEDTLS_SELF_TEST)
496
497 #if !defined(MBEDTLS_SHA1_C)
498 /* Dummy checkup routine */
mbedtls_hmac_drbg_self_test(int verbose)499 int mbedtls_hmac_drbg_self_test( int verbose )
500 {
501 (void) verbose;
502 return( 0 );
503 }
504 #else
505
506 #define OUTPUT_LEN 80
507
508 /* From a NIST PR=true test vector */
509 static const unsigned char entropy_pr[] = {
510 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
511 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
512 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
513 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
514 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
515 static const unsigned char result_pr[OUTPUT_LEN] = {
516 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
517 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
518 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
519 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
520 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
521 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
522 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
523
524 /* From a NIST PR=false test vector */
525 static const unsigned char entropy_nopr[] = {
526 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
527 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
528 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
529 0xe9, 0x9d, 0xfe, 0xdf };
530 static const unsigned char result_nopr[OUTPUT_LEN] = {
531 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
532 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
533 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
534 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
535 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
536 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
537 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
538
539 /* "Entropy" from buffer */
540 static size_t test_offset;
hmac_drbg_self_test_entropy(void * data,unsigned char * buf,size_t len)541 static int hmac_drbg_self_test_entropy( void *data,
542 unsigned char *buf, size_t len )
543 {
544 const unsigned char *p = data;
545 memcpy( buf, p + test_offset, len );
546 test_offset += len;
547 return( 0 );
548 }
549
550 #define CHK( c ) if( (c) != 0 ) \
551 { \
552 if( verbose != 0 ) \
553 mbedtls_printf( "failed\n" ); \
554 return( 1 ); \
555 }
556
557 /*
558 * Checkup routine for HMAC_DRBG with SHA-1
559 */
mbedtls_hmac_drbg_self_test(int verbose)560 int mbedtls_hmac_drbg_self_test( int verbose )
561 {
562 mbedtls_hmac_drbg_context ctx;
563 unsigned char buf[OUTPUT_LEN];
564 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
565
566 mbedtls_hmac_drbg_init( &ctx );
567
568 /*
569 * PR = True
570 */
571 if( verbose != 0 )
572 mbedtls_printf( " HMAC_DRBG (PR = True) : " );
573
574 test_offset = 0;
575 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
576 hmac_drbg_self_test_entropy, (void *) entropy_pr,
577 NULL, 0 ) );
578 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
579 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
580 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
581 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
582 mbedtls_hmac_drbg_free( &ctx );
583
584 mbedtls_hmac_drbg_free( &ctx );
585
586 if( verbose != 0 )
587 mbedtls_printf( "passed\n" );
588
589 /*
590 * PR = False
591 */
592 if( verbose != 0 )
593 mbedtls_printf( " HMAC_DRBG (PR = False) : " );
594
595 mbedtls_hmac_drbg_init( &ctx );
596
597 test_offset = 0;
598 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
599 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
600 NULL, 0 ) );
601 CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
602 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
603 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
604 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
605 mbedtls_hmac_drbg_free( &ctx );
606
607 mbedtls_hmac_drbg_free( &ctx );
608
609 if( verbose != 0 )
610 mbedtls_printf( "passed\n" );
611
612 if( verbose != 0 )
613 mbedtls_printf( "\n" );
614
615 return( 0 );
616 }
617 #endif /* MBEDTLS_SHA1_C */
618 #endif /* MBEDTLS_SELF_TEST */
619
620 #endif /* MBEDTLS_HMAC_DRBG_C */
621