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"
37 #include "mbedtls/platform_util.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 */
55 * HMAC_DRBG context initialization
57 void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx )
59 memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) );
61 #if defined(MBEDTLS_THREADING_C)
62 mbedtls_mutex_init( &ctx->mutex );
67 * HMAC_DRBG update, using optional additional data (10.1.2.2)
69 int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx,
70 const unsigned char *additional,
73 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
74 unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
76 unsigned char K[MBEDTLS_MD_MAX_SIZE];
79 for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
82 if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
84 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
85 ctx->V, md_len ) ) != 0 )
87 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
92 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
93 additional, add_len ) ) != 0 )
96 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, K ) ) != 0 )
100 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ) ) != 0 )
102 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
103 ctx->V, md_len ) ) != 0 )
105 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
110 mbedtls_platform_zeroize( K, sizeof( K ) );
114 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
115 void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
116 const unsigned char *additional,
119 (void) mbedtls_hmac_drbg_update_ret( ctx, additional, add_len );
121 #endif /* MBEDTLS_DEPRECATED_REMOVED */
124 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
126 int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
127 const mbedtls_md_info_t * md_info,
128 const unsigned char *data, size_t data_len )
132 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
136 * Set initial working state.
137 * Use the V memory location, which is currently all 0, to initialize the
138 * MD context with an all-zero key. Then set V to its initial value.
140 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V,
141 mbedtls_md_get_size( md_info ) ) ) != 0 )
143 memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) );
145 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, data, data_len ) ) != 0 )
152 * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
154 int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
155 const unsigned char *additional, size_t len )
157 unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
161 /* III. Check input length */
162 if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
163 ctx->entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT )
165 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
168 memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
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 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
175 seedlen = ctx->entropy_len;
177 /* 1. Concatenate entropy and additional data if any */
178 if( additional != NULL && len != 0 )
180 memcpy( seed + seedlen, additional, len );
184 /* 2. Update state */
185 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, seed, seedlen ) ) != 0 )
188 /* 3. Reset reseed_counter */
189 ctx->reseed_counter = 1;
193 mbedtls_platform_zeroize( seed, seedlen );
198 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
200 int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
201 const mbedtls_md_info_t * md_info,
202 int (*f_entropy)(void *, unsigned char *, size_t),
204 const unsigned char *custom,
208 size_t entropy_len, md_size;
210 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
213 md_size = mbedtls_md_get_size( md_info );
216 * Set initial working state.
217 * Use the V memory location, which is currently all 0, to initialize the
218 * MD context with an all-zero key. Then set V to its initial value.
220 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ) ) != 0 )
222 memset( ctx->V, 0x01, md_size );
224 ctx->f_entropy = f_entropy;
225 ctx->p_entropy = p_entropy;
227 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
230 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
231 * each hash function, then according to SP800-90A rev1 10.1 table 2,
232 * min_entropy_len (in bits) is security_strength.
234 * (This also matches the sizes used in the NIST test vectors.)
236 entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
237 md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
238 32; /* better (256+) -> 256 bits */
241 * For initialisation, use more entropy to emulate a nonce
242 * (Again, matches test vectors.)
244 ctx->entropy_len = entropy_len * 3 / 2;
246 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
249 ctx->entropy_len = entropy_len;
255 * Set prediction resistance
257 void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
260 ctx->prediction_resistance = resistance;
264 * Set entropy length grabbed for reseeds
266 void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
268 ctx->entropy_len = len;
272 * Set reseed interval
274 void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval )
276 ctx->reseed_interval = interval;
280 * HMAC_DRBG random function with optional additional data:
281 * 10.1.2.5 (arabic) + 9.3 (Roman)
283 int mbedtls_hmac_drbg_random_with_add( void *p_rng,
284 unsigned char *output, size_t out_len,
285 const unsigned char *additional, size_t add_len )
288 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
289 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
290 size_t left = out_len;
291 unsigned char *out = output;
293 /* II. Check request length */
294 if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST )
295 return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
297 /* III. Check input length */
298 if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
299 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
301 /* 1. (aka VII and IX) Check reseed counter and PR */
302 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
303 ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
304 ctx->reseed_counter > ctx->reseed_interval ) )
306 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
309 add_len = 0; /* VII.4 */
312 /* 2. Use additional data if any */
313 if( additional != NULL && add_len != 0 )
315 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
316 additional, add_len ) ) != 0 )
320 /* 3, 4, 5. Generate bytes */
323 size_t use_len = left > md_len ? md_len : left;
325 if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
327 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
328 ctx->V, md_len ) ) != 0 )
330 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
333 memcpy( out, ctx->V, use_len );
339 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
340 additional, add_len ) ) != 0 )
343 /* 7. Update reseed counter */
344 ctx->reseed_counter++;
352 * HMAC_DRBG random function
354 int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
357 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
359 #if defined(MBEDTLS_THREADING_C)
360 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
364 ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
366 #if defined(MBEDTLS_THREADING_C)
367 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
368 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
375 * Free an HMAC_DRBG context
377 void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
382 #if defined(MBEDTLS_THREADING_C)
383 mbedtls_mutex_free( &ctx->mutex );
385 mbedtls_md_free( &ctx->md_ctx );
386 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
389 #if defined(MBEDTLS_FS_IO)
390 int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
394 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
396 if( ( f = fopen( path, "wb" ) ) == NULL )
397 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
399 if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
402 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
404 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
412 mbedtls_platform_zeroize( buf, sizeof( buf ) );
417 int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
422 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
425 if( ( f = fopen( path, "rb" ) ) == NULL )
426 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
428 n = fread( buf, 1, sizeof( buf ), f );
429 if( fread( &c, 1, 1, f ) != 0 )
431 ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
434 if( n == 0 || ferror( f ) )
436 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
442 ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n );
445 mbedtls_platform_zeroize( buf, sizeof( buf ) );
450 return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
452 #endif /* MBEDTLS_FS_IO */
455 #if defined(MBEDTLS_SELF_TEST)
457 #if !defined(MBEDTLS_SHA1_C)
458 /* Dummy checkup routine */
459 int mbedtls_hmac_drbg_self_test( int verbose )
466 #define OUTPUT_LEN 80
468 /* From a NIST PR=true test vector */
469 static const unsigned char entropy_pr[] = {
470 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
471 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
472 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
473 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
474 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
475 static const unsigned char result_pr[OUTPUT_LEN] = {
476 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
477 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
478 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
479 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
480 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
481 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
482 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
484 /* From a NIST PR=false test vector */
485 static const unsigned char entropy_nopr[] = {
486 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
487 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
488 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
489 0xe9, 0x9d, 0xfe, 0xdf };
490 static const unsigned char result_nopr[OUTPUT_LEN] = {
491 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
492 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
493 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
494 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
495 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
496 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
497 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
499 /* "Entropy" from buffer */
500 static size_t test_offset;
501 static int hmac_drbg_self_test_entropy( void *data,
502 unsigned char *buf, size_t len )
504 const unsigned char *p = data;
505 memcpy( buf, p + test_offset, len );
510 #define CHK( c ) if( (c) != 0 ) \
513 mbedtls_printf( "failed\n" ); \
518 * Checkup routine for HMAC_DRBG with SHA-1
520 int mbedtls_hmac_drbg_self_test( int verbose )
522 mbedtls_hmac_drbg_context ctx;
523 unsigned char buf[OUTPUT_LEN];
524 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
526 mbedtls_hmac_drbg_init( &ctx );
532 mbedtls_printf( " HMAC_DRBG (PR = True) : " );
535 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
536 hmac_drbg_self_test_entropy, (void *) entropy_pr,
538 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
539 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
540 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
541 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
542 mbedtls_hmac_drbg_free( &ctx );
544 mbedtls_hmac_drbg_free( &ctx );
547 mbedtls_printf( "passed\n" );
553 mbedtls_printf( " HMAC_DRBG (PR = False) : " );
555 mbedtls_hmac_drbg_init( &ctx );
558 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
559 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
561 CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
562 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
563 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
564 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
565 mbedtls_hmac_drbg_free( &ctx );
567 mbedtls_hmac_drbg_free( &ctx );
570 mbedtls_printf( "passed\n" );
573 mbedtls_printf( "\n" );
577 #endif /* MBEDTLS_SHA1_C */
578 #endif /* MBEDTLS_SELF_TEST */
580 #endif /* MBEDTLS_HMAC_DRBG_C */