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_ret(mbedtls_hmac_drbg_context * ctx,const unsigned char * additional,size_t add_len)62 int mbedtls_hmac_drbg_update_ret( 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 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
mbedtls_hmac_drbg_update(mbedtls_hmac_drbg_context * ctx,const unsigned char * additional,size_t add_len)108 void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
109 const unsigned char *additional,
110 size_t add_len )
111 {
112 (void) mbedtls_hmac_drbg_update_ret( ctx, additional, add_len );
113 }
114 #endif /* MBEDTLS_DEPRECATED_REMOVED */
115
116 /*
117 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
118 */
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)119 int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
120 const mbedtls_md_info_t * md_info,
121 const unsigned char *data, size_t data_len )
122 {
123 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
124
125 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
126 return( ret );
127
128 #if defined(MBEDTLS_THREADING_C)
129 mbedtls_mutex_init( &ctx->mutex );
130 #endif
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 /* The mutex is initialized iff the md context is set up. */
258 #if defined(MBEDTLS_THREADING_C)
259 mbedtls_mutex_init( &ctx->mutex );
260 #endif
261
262 md_size = mbedtls_md_get_size( md_info );
263
264 /*
265 * Set initial working state.
266 * Use the V memory location, which is currently all 0, to initialize the
267 * MD context with an all-zero key. Then set V to its initial value.
268 */
269 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ) ) != 0 )
270 return( ret );
271 memset( ctx->V, 0x01, md_size );
272
273 ctx->f_entropy = f_entropy;
274 ctx->p_entropy = p_entropy;
275
276 if( ctx->entropy_len == 0 )
277 {
278 /*
279 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
280 * each hash function, then according to SP800-90A rev1 10.1 table 2,
281 * min_entropy_len (in bits) is security_strength.
282 *
283 * (This also matches the sizes used in the NIST test vectors.)
284 */
285 ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
286 md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
287 32; /* better (256+) -> 256 bits */
288 }
289
290 if( ( ret = hmac_drbg_reseed_core( ctx, custom, len,
291 1 /* add nonce */ ) ) != 0 )
292 {
293 return( ret );
294 }
295
296 return( 0 );
297 }
298
299 /*
300 * Set prediction resistance
301 */
mbedtls_hmac_drbg_set_prediction_resistance(mbedtls_hmac_drbg_context * ctx,int resistance)302 void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
303 int resistance )
304 {
305 ctx->prediction_resistance = resistance;
306 }
307
308 /*
309 * Set entropy length grabbed for seeding
310 */
mbedtls_hmac_drbg_set_entropy_len(mbedtls_hmac_drbg_context * ctx,size_t len)311 void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
312 {
313 ctx->entropy_len = len;
314 }
315
316 /*
317 * Set reseed interval
318 */
mbedtls_hmac_drbg_set_reseed_interval(mbedtls_hmac_drbg_context * ctx,int interval)319 void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval )
320 {
321 ctx->reseed_interval = interval;
322 }
323
324 /*
325 * HMAC_DRBG random function with optional additional data:
326 * 10.1.2.5 (arabic) + 9.3 (Roman)
327 */
mbedtls_hmac_drbg_random_with_add(void * p_rng,unsigned char * output,size_t out_len,const unsigned char * additional,size_t add_len)328 int mbedtls_hmac_drbg_random_with_add( void *p_rng,
329 unsigned char *output, size_t out_len,
330 const unsigned char *additional, size_t add_len )
331 {
332 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
333 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
334 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
335 size_t left = out_len;
336 unsigned char *out = output;
337
338 /* II. Check request length */
339 if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST )
340 return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
341
342 /* III. Check input length */
343 if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
344 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
345
346 /* 1. (aka VII and IX) Check reseed counter and PR */
347 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
348 ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
349 ctx->reseed_counter > ctx->reseed_interval ) )
350 {
351 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
352 return( ret );
353
354 add_len = 0; /* VII.4 */
355 }
356
357 /* 2. Use additional data if any */
358 if( additional != NULL && add_len != 0 )
359 {
360 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
361 additional, add_len ) ) != 0 )
362 goto exit;
363 }
364
365 /* 3, 4, 5. Generate bytes */
366 while( left != 0 )
367 {
368 size_t use_len = left > md_len ? md_len : left;
369
370 if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
371 goto exit;
372 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
373 ctx->V, md_len ) ) != 0 )
374 goto exit;
375 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
376 goto exit;
377
378 memcpy( out, ctx->V, use_len );
379 out += use_len;
380 left -= use_len;
381 }
382
383 /* 6. Update */
384 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
385 additional, add_len ) ) != 0 )
386 goto exit;
387
388 /* 7. Update reseed counter */
389 ctx->reseed_counter++;
390
391 exit:
392 /* 8. Done */
393 return( ret );
394 }
395
396 /*
397 * HMAC_DRBG random function
398 */
mbedtls_hmac_drbg_random(void * p_rng,unsigned char * output,size_t out_len)399 int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
400 {
401 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
402 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
403
404 #if defined(MBEDTLS_THREADING_C)
405 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
406 return( ret );
407 #endif
408
409 ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
410
411 #if defined(MBEDTLS_THREADING_C)
412 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
413 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
414 #endif
415
416 return( ret );
417 }
418
419 /*
420 * This function resets HMAC_DRBG context to the state immediately
421 * after initial call of mbedtls_hmac_drbg_init().
422 */
mbedtls_hmac_drbg_free(mbedtls_hmac_drbg_context * ctx)423 void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
424 {
425 if( ctx == NULL )
426 return;
427
428 #if defined(MBEDTLS_THREADING_C)
429 /* The mutex is initialized iff the md context is set up. */
430 if( ctx->md_ctx.md_info != NULL )
431 mbedtls_mutex_free( &ctx->mutex );
432 #endif
433 mbedtls_md_free( &ctx->md_ctx );
434 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
435 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
436 }
437
438 #if defined(MBEDTLS_FS_IO)
mbedtls_hmac_drbg_write_seed_file(mbedtls_hmac_drbg_context * ctx,const char * path)439 int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
440 {
441 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
442 FILE *f;
443 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
444
445 if( ( f = fopen( path, "wb" ) ) == NULL )
446 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
447
448 if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
449 goto exit;
450
451 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
452 {
453 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
454 goto exit;
455 }
456
457 ret = 0;
458
459 exit:
460 fclose( f );
461 mbedtls_platform_zeroize( buf, sizeof( buf ) );
462
463 return( ret );
464 }
465
mbedtls_hmac_drbg_update_seed_file(mbedtls_hmac_drbg_context * ctx,const char * path)466 int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
467 {
468 int ret = 0;
469 FILE *f = NULL;
470 size_t n;
471 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
472 unsigned char c;
473
474 if( ( f = fopen( path, "rb" ) ) == NULL )
475 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
476
477 n = fread( buf, 1, sizeof( buf ), f );
478 if( fread( &c, 1, 1, f ) != 0 )
479 {
480 ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
481 goto exit;
482 }
483 if( n == 0 || ferror( f ) )
484 {
485 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
486 goto exit;
487 }
488 fclose( f );
489 f = NULL;
490
491 ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n );
492
493 exit:
494 mbedtls_platform_zeroize( buf, sizeof( buf ) );
495 if( f != NULL )
496 fclose( f );
497 if( ret != 0 )
498 return( ret );
499 return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
500 }
501 #endif /* MBEDTLS_FS_IO */
502
503
504 #if defined(MBEDTLS_SELF_TEST)
505
506 #if !defined(MBEDTLS_SHA1_C)
507 /* Dummy checkup routine */
mbedtls_hmac_drbg_self_test(int verbose)508 int mbedtls_hmac_drbg_self_test( int verbose )
509 {
510 (void) verbose;
511 return( 0 );
512 }
513 #else
514
515 #define OUTPUT_LEN 80
516
517 /* From a NIST PR=true test vector */
518 static const unsigned char entropy_pr[] = {
519 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
520 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
521 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
522 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
523 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
524 static const unsigned char result_pr[OUTPUT_LEN] = {
525 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
526 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
527 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
528 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
529 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
530 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
531 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
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 static const unsigned char result_nopr[OUTPUT_LEN] = {
540 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
541 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
542 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
543 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
544 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
545 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
546 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
547
548 /* "Entropy" from buffer */
549 static size_t test_offset;
hmac_drbg_self_test_entropy(void * data,unsigned char * buf,size_t len)550 static int hmac_drbg_self_test_entropy( void *data,
551 unsigned char *buf, size_t len )
552 {
553 const unsigned char *p = data;
554 memcpy( buf, p + test_offset, len );
555 test_offset += len;
556 return( 0 );
557 }
558
559 #define CHK( c ) if( (c) != 0 ) \
560 { \
561 if( verbose != 0 ) \
562 mbedtls_printf( "failed\n" ); \
563 return( 1 ); \
564 }
565
566 /*
567 * Checkup routine for HMAC_DRBG with SHA-1
568 */
mbedtls_hmac_drbg_self_test(int verbose)569 int mbedtls_hmac_drbg_self_test( int verbose )
570 {
571 mbedtls_hmac_drbg_context ctx;
572 unsigned char buf[OUTPUT_LEN];
573 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
574
575 mbedtls_hmac_drbg_init( &ctx );
576
577 /*
578 * PR = True
579 */
580 if( verbose != 0 )
581 mbedtls_printf( " HMAC_DRBG (PR = True) : " );
582
583 test_offset = 0;
584 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
585 hmac_drbg_self_test_entropy, (void *) entropy_pr,
586 NULL, 0 ) );
587 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
588 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
589 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
590 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
591 mbedtls_hmac_drbg_free( &ctx );
592
593 mbedtls_hmac_drbg_free( &ctx );
594
595 if( verbose != 0 )
596 mbedtls_printf( "passed\n" );
597
598 /*
599 * PR = False
600 */
601 if( verbose != 0 )
602 mbedtls_printf( " HMAC_DRBG (PR = False) : " );
603
604 mbedtls_hmac_drbg_init( &ctx );
605
606 test_offset = 0;
607 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
608 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
609 NULL, 0 ) );
610 CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
611 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
612 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
613 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
614 mbedtls_hmac_drbg_free( &ctx );
615
616 mbedtls_hmac_drbg_free( &ctx );
617
618 if( verbose != 0 )
619 mbedtls_printf( "passed\n" );
620
621 if( verbose != 0 )
622 mbedtls_printf( "\n" );
623
624 return( 0 );
625 }
626 #endif /* MBEDTLS_SHA1_C */
627 #endif /* MBEDTLS_SELF_TEST */
628
629 #endif /* MBEDTLS_HMAC_DRBG_C */
630