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