2 * HMAC_DRBG implementation (NIST SP 800-90)
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 * SPDX-License-Identifier: Apache-2.0
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 * This file is part of mbed TLS (https://tls.mbed.org)
23 * The NIST SP 800-90A DRBGs are described in the following publication.
24 * http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
25 * References below are based on rev. 1 (January 2012).
28 #if !defined(MBEDTLS_CONFIG_FILE)
29 #include "mbedtls/config.h"
31 #include MBEDTLS_CONFIG_FILE
34 #if defined(MBEDTLS_HMAC_DRBG_C)
36 #include "mbedtls/hmac_drbg.h"
40 #if defined(MBEDTLS_FS_IO)
44 #if defined(MBEDTLS_SELF_TEST)
45 #if defined(MBEDTLS_PLATFORM_C)
46 #include "mbedtls/platform.h"
49 #define mbedtls_printf printf
50 #endif /* MBEDTLS_SELF_TEST */
51 #endif /* MBEDTLS_PLATFORM_C */
53 /* Implementation that should never be optimized out by the compiler */
54 static void mbedtls_zeroize( void *v, size_t n ) {
55 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
59 * HMAC_DRBG context initialization
61 void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx )
63 memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) );
65 #if defined(MBEDTLS_THREADING_C)
66 mbedtls_mutex_init( &ctx->mutex );
71 * HMAC_DRBG update, using optional additional data (10.1.2.2)
73 void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
74 const unsigned char *additional, size_t add_len )
76 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
77 unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
79 unsigned char K[MBEDTLS_MD_MAX_SIZE];
81 for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
84 mbedtls_md_hmac_reset( &ctx->md_ctx );
85 mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
86 mbedtls_md_hmac_update( &ctx->md_ctx, sep, 1 );
88 mbedtls_md_hmac_update( &ctx->md_ctx, additional, add_len );
89 mbedtls_md_hmac_finish( &ctx->md_ctx, K );
92 mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len );
93 mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
94 mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V );
99 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
101 int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
102 const mbedtls_md_info_t * md_info,
103 const unsigned char *data, size_t data_len )
107 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
111 * Set initial working state.
112 * Use the V memory location, which is currently all 0, to initialize the
113 * MD context with an all-zero key. Then set V to its initial value.
115 mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, mbedtls_md_get_size( md_info ) );
116 memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) );
118 mbedtls_hmac_drbg_update( ctx, data, data_len );
124 * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
126 int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
127 const unsigned char *additional, size_t len )
129 unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
132 /* III. Check input length */
133 if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
134 ctx->entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT )
136 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
139 memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
141 /* IV. Gather entropy_len bytes of entropy for the seed */
142 if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 )
143 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
145 seedlen = ctx->entropy_len;
147 /* 1. Concatenate entropy and additional data if any */
148 if( additional != NULL && len != 0 )
150 memcpy( seed + seedlen, additional, len );
154 /* 2. Update state */
155 mbedtls_hmac_drbg_update( ctx, seed, seedlen );
157 /* 3. Reset reseed_counter */
158 ctx->reseed_counter = 1;
165 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
167 int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
168 const mbedtls_md_info_t * md_info,
169 int (*f_entropy)(void *, unsigned char *, size_t),
171 const unsigned char *custom,
175 size_t entropy_len, md_size;
177 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
180 md_size = mbedtls_md_get_size( md_info );
183 * Set initial working state.
184 * Use the V memory location, which is currently all 0, to initialize the
185 * MD context with an all-zero key. Then set V to its initial value.
187 mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size );
188 memset( ctx->V, 0x01, md_size );
190 ctx->f_entropy = f_entropy;
191 ctx->p_entropy = p_entropy;
193 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
196 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
197 * each hash function, then according to SP800-90A rev1 10.1 table 2,
198 * min_entropy_len (in bits) is security_strength.
200 * (This also matches the sizes used in the NIST test vectors.)
202 entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
203 md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
204 32; /* better (256+) -> 256 bits */
207 * For initialisation, use more entropy to emulate a nonce
208 * (Again, matches test vectors.)
210 ctx->entropy_len = entropy_len * 3 / 2;
212 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
215 ctx->entropy_len = entropy_len;
221 * Set prediction resistance
223 void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
226 ctx->prediction_resistance = resistance;
230 * Set entropy length grabbed for reseeds
232 void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
234 ctx->entropy_len = len;
238 * Set reseed interval
240 void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval )
242 ctx->reseed_interval = interval;
246 * HMAC_DRBG random function with optional additional data:
247 * 10.1.2.5 (arabic) + 9.3 (Roman)
249 int mbedtls_hmac_drbg_random_with_add( void *p_rng,
250 unsigned char *output, size_t out_len,
251 const unsigned char *additional, size_t add_len )
254 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
255 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
256 size_t left = out_len;
257 unsigned char *out = output;
259 /* II. Check request length */
260 if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST )
261 return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
263 /* III. Check input length */
264 if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
265 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
267 /* 1. (aka VII and IX) Check reseed counter and PR */
268 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
269 ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
270 ctx->reseed_counter > ctx->reseed_interval ) )
272 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
275 add_len = 0; /* VII.4 */
278 /* 2. Use additional data if any */
279 if( additional != NULL && add_len != 0 )
280 mbedtls_hmac_drbg_update( ctx, additional, add_len );
282 /* 3, 4, 5. Generate bytes */
285 size_t use_len = left > md_len ? md_len : left;
287 mbedtls_md_hmac_reset( &ctx->md_ctx );
288 mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
289 mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V );
291 memcpy( out, ctx->V, use_len );
297 mbedtls_hmac_drbg_update( ctx, additional, add_len );
299 /* 7. Update reseed counter */
300 ctx->reseed_counter++;
307 * HMAC_DRBG random function
309 int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
312 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
314 #if defined(MBEDTLS_THREADING_C)
315 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
319 ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
321 #if defined(MBEDTLS_THREADING_C)
322 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
323 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
330 * Free an HMAC_DRBG context
332 void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
337 #if defined(MBEDTLS_THREADING_C)
338 mbedtls_mutex_free( &ctx->mutex );
340 mbedtls_md_free( &ctx->md_ctx );
341 mbedtls_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
344 #if defined(MBEDTLS_FS_IO)
345 int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
349 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
351 if( ( f = fopen( path, "wb" ) ) == NULL )
352 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
354 if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
357 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
359 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
370 int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
374 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
376 if( ( f = fopen( path, "rb" ) ) == NULL )
377 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
379 fseek( f, 0, SEEK_END );
380 n = (size_t) ftell( f );
381 fseek( f, 0, SEEK_SET );
383 if( n > MBEDTLS_HMAC_DRBG_MAX_INPUT )
386 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
389 if( fread( buf, 1, n, f ) != n )
392 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
397 mbedtls_hmac_drbg_update( ctx, buf, n );
399 return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
401 #endif /* MBEDTLS_FS_IO */
404 #if defined(MBEDTLS_SELF_TEST)
406 #if !defined(MBEDTLS_SHA1_C)
407 /* Dummy checkup routine */
408 int mbedtls_hmac_drbg_self_test( int verbose )
415 #define OUTPUT_LEN 80
417 /* From a NIST PR=true test vector */
418 static const unsigned char entropy_pr[] = {
419 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
420 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
421 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
422 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
423 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
424 static const unsigned char result_pr[OUTPUT_LEN] = {
425 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
426 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
427 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
428 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
429 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
430 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
431 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
433 /* From a NIST PR=false test vector */
434 static const unsigned char entropy_nopr[] = {
435 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
436 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
437 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
438 0xe9, 0x9d, 0xfe, 0xdf };
439 static const unsigned char result_nopr[OUTPUT_LEN] = {
440 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
441 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
442 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
443 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
444 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
445 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
446 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
448 /* "Entropy" from buffer */
449 static size_t test_offset;
450 static int hmac_drbg_self_test_entropy( void *data,
451 unsigned char *buf, size_t len )
453 const unsigned char *p = data;
454 memcpy( buf, p + test_offset, len );
459 #define CHK( c ) if( (c) != 0 ) \
462 mbedtls_printf( "failed\n" ); \
467 * Checkup routine for HMAC_DRBG with SHA-1
469 int mbedtls_hmac_drbg_self_test( int verbose )
471 mbedtls_hmac_drbg_context ctx;
472 unsigned char buf[OUTPUT_LEN];
473 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
475 mbedtls_hmac_drbg_init( &ctx );
481 mbedtls_printf( " HMAC_DRBG (PR = True) : " );
484 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
485 hmac_drbg_self_test_entropy, (void *) entropy_pr,
487 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
488 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
489 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
490 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
491 mbedtls_hmac_drbg_free( &ctx );
493 mbedtls_hmac_drbg_free( &ctx );
496 mbedtls_printf( "passed\n" );
502 mbedtls_printf( " HMAC_DRBG (PR = False) : " );
504 mbedtls_hmac_drbg_init( &ctx );
507 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
508 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
510 CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
511 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
512 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
513 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
514 mbedtls_hmac_drbg_free( &ctx );
516 mbedtls_hmac_drbg_free( &ctx );
519 mbedtls_printf( "passed\n" );
522 mbedtls_printf( "\n" );
526 #endif /* MBEDTLS_SHA1_C */
527 #endif /* MBEDTLS_SELF_TEST */
529 #endif /* MBEDTLS_HMAC_DRBG_C */