2 * HMAC_DRBG implementation (NIST SP 800-90)
4 * Copyright (C) 2014, ARM Limited, All Rights Reserved
6 * This file is part of mbed TLS (https://tls.mbed.org)
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * The NIST SP 800-90A DRBGs are described in the following publication.
25 * http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
26 * References below are based on rev. 1 (January 2012).
29 #if !defined(MBEDTLS_CONFIG_FILE)
30 #include "mbedtls/config.h"
32 #include MBEDTLS_CONFIG_FILE
35 #if defined(MBEDTLS_HMAC_DRBG_C)
37 #include "mbedtls/hmac_drbg.h"
41 #if defined(MBEDTLS_FS_IO)
45 #if defined(MBEDTLS_SELF_TEST)
46 #if defined(MBEDTLS_PLATFORM_C)
47 #include "mbedtls/platform.h"
50 #define mbedtls_printf printf
51 #endif /* MBEDTLS_SELF_TEST */
52 #endif /* MBEDTLS_PLATFORM_C */
54 /* Implementation that should never be optimized out by the compiler */
55 static void mbedtls_zeroize( void *v
, size_t n
) {
56 volatile unsigned char *p
= v
; while( n
-- ) *p
++ = 0;
60 * HMAC_DRBG context initialization
62 void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context
*ctx
)
64 memset( ctx
, 0, sizeof( mbedtls_hmac_drbg_context
) );
66 #if defined(MBEDTLS_THREADING_C)
67 mbedtls_mutex_init( &ctx
->mutex
);
72 * HMAC_DRBG update, using optional additional data (10.1.2.2)
74 void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context
*ctx
,
75 const unsigned char *additional
, size_t add_len
)
77 size_t md_len
= mbedtls_md_get_size( ctx
->md_ctx
.md_info
);
78 unsigned char rounds
= ( additional
!= NULL
&& add_len
!= 0 ) ? 2 : 1;
80 unsigned char K
[MBEDTLS_MD_MAX_SIZE
];
82 for( sep
[0] = 0; sep
[0] < rounds
; sep
[0]++ )
85 mbedtls_md_hmac_reset( &ctx
->md_ctx
);
86 mbedtls_md_hmac_update( &ctx
->md_ctx
, ctx
->V
, md_len
);
87 mbedtls_md_hmac_update( &ctx
->md_ctx
, sep
, 1 );
89 mbedtls_md_hmac_update( &ctx
->md_ctx
, additional
, add_len
);
90 mbedtls_md_hmac_finish( &ctx
->md_ctx
, K
);
93 mbedtls_md_hmac_starts( &ctx
->md_ctx
, K
, md_len
);
94 mbedtls_md_hmac_update( &ctx
->md_ctx
, ctx
->V
, md_len
);
95 mbedtls_md_hmac_finish( &ctx
->md_ctx
, ctx
->V
);
100 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
102 int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context
*ctx
,
103 const mbedtls_md_info_t
* md_info
,
104 const unsigned char *data
, size_t data_len
)
108 if( ( ret
= mbedtls_md_setup( &ctx
->md_ctx
, md_info
, 1 ) ) != 0 )
112 * Set initial working state.
113 * Use the V memory location, which is currently all 0, to initialize the
114 * MD context with an all-zero key. Then set V to its initial value.
116 mbedtls_md_hmac_starts( &ctx
->md_ctx
, ctx
->V
, mbedtls_md_get_size( md_info
) );
117 memset( ctx
->V
, 0x01, mbedtls_md_get_size( md_info
) );
119 mbedtls_hmac_drbg_update( ctx
, data
, data_len
);
125 * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
127 int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context
*ctx
,
128 const unsigned char *additional
, size_t len
)
130 unsigned char seed
[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT
];
133 /* III. Check input length */
134 if( len
> MBEDTLS_HMAC_DRBG_MAX_INPUT
||
135 ctx
->entropy_len
+ len
> MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT
)
137 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG
);
140 memset( seed
, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT
);
142 /* IV. Gather entropy_len bytes of entropy for the seed */
143 if( ctx
->f_entropy( ctx
->p_entropy
, seed
, ctx
->entropy_len
) != 0 )
144 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
);
146 seedlen
= ctx
->entropy_len
;
148 /* 1. Concatenate entropy and additional data if any */
149 if( additional
!= NULL
&& len
!= 0 )
151 memcpy( seed
+ seedlen
, additional
, len
);
155 /* 2. Update state */
156 mbedtls_hmac_drbg_update( ctx
, seed
, seedlen
);
158 /* 3. Reset reseed_counter */
159 ctx
->reseed_counter
= 1;
166 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
168 int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context
*ctx
,
169 const mbedtls_md_info_t
* md_info
,
170 int (*f_entropy
)(void *, unsigned char *, size_t),
172 const unsigned char *custom
,
176 size_t entropy_len
, md_size
;
178 if( ( ret
= mbedtls_md_setup( &ctx
->md_ctx
, md_info
, 1 ) ) != 0 )
181 md_size
= mbedtls_md_get_size( md_info
);
184 * Set initial working state.
185 * Use the V memory location, which is currently all 0, to initialize the
186 * MD context with an all-zero key. Then set V to its initial value.
188 mbedtls_md_hmac_starts( &ctx
->md_ctx
, ctx
->V
, md_size
);
189 memset( ctx
->V
, 0x01, md_size
);
191 ctx
->f_entropy
= f_entropy
;
192 ctx
->p_entropy
= p_entropy
;
194 ctx
->reseed_interval
= MBEDTLS_HMAC_DRBG_RESEED_INTERVAL
;
197 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
198 * each hash function, then according to SP800-90A rev1 10.1 table 2,
199 * min_entropy_len (in bits) is security_strength.
201 * (This also matches the sizes used in the NIST test vectors.)
203 entropy_len
= md_size
<= 20 ? 16 : /* 160-bits hash -> 128 bits */
204 md_size
<= 28 ? 24 : /* 224-bits hash -> 192 bits */
205 32; /* better (256+) -> 256 bits */
208 * For initialisation, use more entropy to emulate a nonce
209 * (Again, matches test vectors.)
211 ctx
->entropy_len
= entropy_len
* 3 / 2;
213 if( ( ret
= mbedtls_hmac_drbg_reseed( ctx
, custom
, len
) ) != 0 )
216 ctx
->entropy_len
= entropy_len
;
222 * Set prediction resistance
224 void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context
*ctx
,
227 ctx
->prediction_resistance
= resistance
;
231 * Set entropy length grabbed for reseeds
233 void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context
*ctx
, size_t len
)
235 ctx
->entropy_len
= len
;
239 * Set reseed interval
241 void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context
*ctx
, int interval
)
243 ctx
->reseed_interval
= interval
;
247 * HMAC_DRBG random function with optional additional data:
248 * 10.1.2.5 (arabic) + 9.3 (Roman)
250 int mbedtls_hmac_drbg_random_with_add( void *p_rng
,
251 unsigned char *output
, size_t out_len
,
252 const unsigned char *additional
, size_t add_len
)
255 mbedtls_hmac_drbg_context
*ctx
= (mbedtls_hmac_drbg_context
*) p_rng
;
256 size_t md_len
= mbedtls_md_get_size( ctx
->md_ctx
.md_info
);
257 size_t left
= out_len
;
258 unsigned char *out
= output
;
260 /* II. Check request length */
261 if( out_len
> MBEDTLS_HMAC_DRBG_MAX_REQUEST
)
262 return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG
);
264 /* III. Check input length */
265 if( add_len
> MBEDTLS_HMAC_DRBG_MAX_INPUT
)
266 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG
);
268 /* 1. (aka VII and IX) Check reseed counter and PR */
269 if( ctx
->f_entropy
!= NULL
&& /* For no-reseeding instances */
270 ( ctx
->prediction_resistance
== MBEDTLS_HMAC_DRBG_PR_ON
||
271 ctx
->reseed_counter
> ctx
->reseed_interval
) )
273 if( ( ret
= mbedtls_hmac_drbg_reseed( ctx
, additional
, add_len
) ) != 0 )
276 add_len
= 0; /* VII.4 */
279 /* 2. Use additional data if any */
280 if( additional
!= NULL
&& add_len
!= 0 )
281 mbedtls_hmac_drbg_update( ctx
, additional
, add_len
);
283 /* 3, 4, 5. Generate bytes */
286 size_t use_len
= left
> md_len
? md_len
: left
;
288 mbedtls_md_hmac_reset( &ctx
->md_ctx
);
289 mbedtls_md_hmac_update( &ctx
->md_ctx
, ctx
->V
, md_len
);
290 mbedtls_md_hmac_finish( &ctx
->md_ctx
, ctx
->V
);
292 memcpy( out
, ctx
->V
, use_len
);
298 mbedtls_hmac_drbg_update( ctx
, additional
, add_len
);
300 /* 7. Update reseed counter */
301 ctx
->reseed_counter
++;
308 * HMAC_DRBG random function
310 int mbedtls_hmac_drbg_random( void *p_rng
, unsigned char *output
, size_t out_len
)
313 mbedtls_hmac_drbg_context
*ctx
= (mbedtls_hmac_drbg_context
*) p_rng
;
315 #if defined(MBEDTLS_THREADING_C)
316 if( ( ret
= mbedtls_mutex_lock( &ctx
->mutex
) ) != 0 )
320 ret
= mbedtls_hmac_drbg_random_with_add( ctx
, output
, out_len
, NULL
, 0 );
322 #if defined(MBEDTLS_THREADING_C)
323 if( mbedtls_mutex_unlock( &ctx
->mutex
) != 0 )
324 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR
);
331 * Free an HMAC_DRBG context
333 void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context
*ctx
)
338 #if defined(MBEDTLS_THREADING_C)
339 mbedtls_mutex_free( &ctx
->mutex
);
341 mbedtls_md_free( &ctx
->md_ctx
);
342 mbedtls_zeroize( ctx
, sizeof( mbedtls_hmac_drbg_context
) );
345 #if defined(MBEDTLS_FS_IO)
346 int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context
*ctx
, const char *path
)
350 unsigned char buf
[ MBEDTLS_HMAC_DRBG_MAX_INPUT
];
352 if( ( f
= fopen( path
, "wb" ) ) == NULL
)
353 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR
);
355 if( ( ret
= mbedtls_hmac_drbg_random( ctx
, buf
, sizeof( buf
) ) ) != 0 )
358 if( fwrite( buf
, 1, sizeof( buf
), f
) != sizeof( buf
) )
360 ret
= MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR
;
371 int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context
*ctx
, const char *path
)
375 unsigned char buf
[ MBEDTLS_HMAC_DRBG_MAX_INPUT
];
377 if( ( f
= fopen( path
, "rb" ) ) == NULL
)
378 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR
);
380 fseek( f
, 0, SEEK_END
);
381 n
= (size_t) ftell( f
);
382 fseek( f
, 0, SEEK_SET
);
384 if( n
> MBEDTLS_HMAC_DRBG_MAX_INPUT
)
387 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG
);
390 if( fread( buf
, 1, n
, f
) != n
)
393 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR
);
398 mbedtls_hmac_drbg_update( ctx
, buf
, n
);
400 return( mbedtls_hmac_drbg_write_seed_file( ctx
, path
) );
402 #endif /* MBEDTLS_FS_IO */
405 #if defined(MBEDTLS_SELF_TEST)
407 #if !defined(MBEDTLS_SHA1_C)
408 /* Dummy checkup routine */
409 int mbedtls_hmac_drbg_self_test( int verbose
)
413 mbedtls_printf( "\n" );
419 #define OUTPUT_LEN 80
421 /* From a NIST PR=true test vector */
422 static const unsigned char entropy_pr
[] = {
423 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
424 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
425 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
426 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
427 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
428 static const unsigned char result_pr
[OUTPUT_LEN
] = {
429 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
430 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
431 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
432 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
433 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
434 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
435 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
437 /* From a NIST PR=false test vector */
438 static const unsigned char entropy_nopr
[] = {
439 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
440 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
441 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
442 0xe9, 0x9d, 0xfe, 0xdf };
443 static const unsigned char result_nopr
[OUTPUT_LEN
] = {
444 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
445 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
446 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
447 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
448 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
449 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
450 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
452 /* "Entropy" from buffer */
453 static size_t test_offset
;
454 static int hmac_drbg_self_test_entropy( void *data
,
455 unsigned char *buf
, size_t len
)
457 const unsigned char *p
= data
;
458 memcpy( buf
, p
+ test_offset
, len
);
463 #define CHK( c ) if( (c) != 0 ) \
466 mbedtls_printf( "failed\n" ); \
471 * Checkup routine for HMAC_DRBG with SHA-1
473 int mbedtls_hmac_drbg_self_test( int verbose
)
475 mbedtls_hmac_drbg_context ctx
;
476 unsigned char buf
[OUTPUT_LEN
];
477 const mbedtls_md_info_t
*md_info
= mbedtls_md_info_from_type( MBEDTLS_MD_SHA1
);
479 mbedtls_hmac_drbg_init( &ctx
);
485 mbedtls_printf( " HMAC_DRBG (PR = True) : " );
488 CHK( mbedtls_hmac_drbg_seed( &ctx
, md_info
,
489 hmac_drbg_self_test_entropy
, (void *) entropy_pr
,
491 mbedtls_hmac_drbg_set_prediction_resistance( &ctx
, MBEDTLS_HMAC_DRBG_PR_ON
);
492 CHK( mbedtls_hmac_drbg_random( &ctx
, buf
, OUTPUT_LEN
) );
493 CHK( mbedtls_hmac_drbg_random( &ctx
, buf
, OUTPUT_LEN
) );
494 CHK( memcmp( buf
, result_pr
, OUTPUT_LEN
) );
495 mbedtls_hmac_drbg_free( &ctx
);
497 mbedtls_hmac_drbg_free( &ctx
);
500 mbedtls_printf( "passed\n" );
506 mbedtls_printf( " HMAC_DRBG (PR = False) : " );
508 mbedtls_hmac_drbg_init( &ctx
);
511 CHK( mbedtls_hmac_drbg_seed( &ctx
, md_info
,
512 hmac_drbg_self_test_entropy
, (void *) entropy_nopr
,
514 CHK( mbedtls_hmac_drbg_reseed( &ctx
, NULL
, 0 ) );
515 CHK( mbedtls_hmac_drbg_random( &ctx
, buf
, OUTPUT_LEN
) );
516 CHK( mbedtls_hmac_drbg_random( &ctx
, buf
, OUTPUT_LEN
) );
517 CHK( memcmp( buf
, result_nopr
, OUTPUT_LEN
) );
518 mbedtls_hmac_drbg_free( &ctx
);
520 mbedtls_hmac_drbg_free( &ctx
);
523 mbedtls_printf( "passed\n" );
526 mbedtls_printf( "\n" );
530 #endif /* MBEDTLS_SHA1_C */
531 #endif /* MBEDTLS_SELF_TEST */
533 #endif /* MBEDTLS_HMAC_DRBG_C */