2 * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 * SPDX-License-Identifier: GPL-2.0
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 * This file is part of mbed TLS (https://tls.mbed.org)
24 * The NIST SP 800-90 DRBGs are described in the following publication.
26 * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
29 #if !defined(MBEDTLS_CONFIG_FILE)
30 #include "mbedtls/config.h"
32 #include MBEDTLS_CONFIG_FILE
35 #if defined(MBEDTLS_CTR_DRBG_C)
37 #include "mbedtls/ctr_drbg.h"
38 #include "mbedtls/platform_util.h"
42 #if defined(MBEDTLS_FS_IO)
46 #if defined(MBEDTLS_SELF_TEST)
47 #if defined(MBEDTLS_PLATFORM_C)
48 #include "mbedtls/platform.h"
51 #define mbedtls_printf printf
52 #endif /* MBEDTLS_PLATFORM_C */
53 #endif /* MBEDTLS_SELF_TEST */
56 * CTR_DRBG context initialization
58 void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context
*ctx
)
60 memset( ctx
, 0, sizeof( mbedtls_ctr_drbg_context
) );
62 #if defined(MBEDTLS_THREADING_C)
63 mbedtls_mutex_init( &ctx
->mutex
);
68 * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow
69 * NIST tests to succeed (which require known length fixed entropy)
71 int mbedtls_ctr_drbg_seed_entropy_len(
72 mbedtls_ctr_drbg_context
*ctx
,
73 int (*f_entropy
)(void *, unsigned char *, size_t),
75 const unsigned char *custom
,
80 unsigned char key
[MBEDTLS_CTR_DRBG_KEYSIZE
];
82 memset( key
, 0, MBEDTLS_CTR_DRBG_KEYSIZE
);
84 mbedtls_aes_init( &ctx
->aes_ctx
);
86 ctx
->f_entropy
= f_entropy
;
87 ctx
->p_entropy
= p_entropy
;
89 ctx
->entropy_len
= entropy_len
;
90 ctx
->reseed_interval
= MBEDTLS_CTR_DRBG_RESEED_INTERVAL
;
93 * Initialize with an empty key
95 if( ( ret
= mbedtls_aes_setkey_enc( &ctx
->aes_ctx
, key
, MBEDTLS_CTR_DRBG_KEYBITS
) ) != 0 )
100 if( ( ret
= mbedtls_ctr_drbg_reseed( ctx
, custom
, len
) ) != 0 )
107 int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context
*ctx
,
108 int (*f_entropy
)(void *, unsigned char *, size_t),
110 const unsigned char *custom
,
113 return( mbedtls_ctr_drbg_seed_entropy_len( ctx
, f_entropy
, p_entropy
, custom
, len
,
114 MBEDTLS_CTR_DRBG_ENTROPY_LEN
) );
117 void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context
*ctx
)
122 #if defined(MBEDTLS_THREADING_C)
123 mbedtls_mutex_free( &ctx
->mutex
);
125 mbedtls_aes_free( &ctx
->aes_ctx
);
126 mbedtls_platform_zeroize( ctx
, sizeof( mbedtls_ctr_drbg_context
) );
129 void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context
*ctx
, int resistance
)
131 ctx
->prediction_resistance
= resistance
;
134 void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context
*ctx
, size_t len
)
136 ctx
->entropy_len
= len
;
139 void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context
*ctx
, int interval
)
141 ctx
->reseed_interval
= interval
;
144 static int block_cipher_df( unsigned char *output
,
145 const unsigned char *data
, size_t data_len
)
147 unsigned char buf
[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
+ MBEDTLS_CTR_DRBG_BLOCKSIZE
+ 16];
148 unsigned char tmp
[MBEDTLS_CTR_DRBG_SEEDLEN
];
149 unsigned char key
[MBEDTLS_CTR_DRBG_KEYSIZE
];
150 unsigned char chain
[MBEDTLS_CTR_DRBG_BLOCKSIZE
];
151 unsigned char *p
, *iv
;
152 mbedtls_aes_context aes_ctx
;
156 size_t buf_len
, use_len
;
158 if( data_len
> MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
)
159 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG
);
161 memset( buf
, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
+ MBEDTLS_CTR_DRBG_BLOCKSIZE
+ 16 );
162 mbedtls_aes_init( &aes_ctx
);
165 * Construct IV (16 bytes) and S in buffer
166 * IV = Counter (in 32-bits) padded to 16 with zeroes
167 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
169 * (Total is padded to a multiple of 16-bytes with zeroes)
171 p
= buf
+ MBEDTLS_CTR_DRBG_BLOCKSIZE
;
172 *p
++ = ( data_len
>> 24 ) & 0xff;
173 *p
++ = ( data_len
>> 16 ) & 0xff;
174 *p
++ = ( data_len
>> 8 ) & 0xff;
175 *p
++ = ( data_len
) & 0xff;
177 *p
++ = MBEDTLS_CTR_DRBG_SEEDLEN
;
178 memcpy( p
, data
, data_len
);
181 buf_len
= MBEDTLS_CTR_DRBG_BLOCKSIZE
+ 8 + data_len
+ 1;
183 for( i
= 0; i
< MBEDTLS_CTR_DRBG_KEYSIZE
; i
++ )
186 if( ( ret
= mbedtls_aes_setkey_enc( &aes_ctx
, key
, MBEDTLS_CTR_DRBG_KEYBITS
) ) != 0 )
192 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
194 for( j
= 0; j
< MBEDTLS_CTR_DRBG_SEEDLEN
; j
+= MBEDTLS_CTR_DRBG_BLOCKSIZE
)
197 memset( chain
, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE
);
202 for( i
= 0; i
< MBEDTLS_CTR_DRBG_BLOCKSIZE
; i
++ )
204 p
+= MBEDTLS_CTR_DRBG_BLOCKSIZE
;
205 use_len
-= ( use_len
>= MBEDTLS_CTR_DRBG_BLOCKSIZE
) ?
206 MBEDTLS_CTR_DRBG_BLOCKSIZE
: use_len
;
208 if( ( ret
= mbedtls_aes_crypt_ecb( &aes_ctx
, MBEDTLS_AES_ENCRYPT
, chain
, chain
) ) != 0 )
214 memcpy( tmp
+ j
, chain
, MBEDTLS_CTR_DRBG_BLOCKSIZE
);
223 * Do final encryption with reduced data
225 if( ( ret
= mbedtls_aes_setkey_enc( &aes_ctx
, tmp
, MBEDTLS_CTR_DRBG_KEYBITS
) ) != 0 )
229 iv
= tmp
+ MBEDTLS_CTR_DRBG_KEYSIZE
;
232 for( j
= 0; j
< MBEDTLS_CTR_DRBG_SEEDLEN
; j
+= MBEDTLS_CTR_DRBG_BLOCKSIZE
)
234 if( ( ret
= mbedtls_aes_crypt_ecb( &aes_ctx
, MBEDTLS_AES_ENCRYPT
, iv
, iv
) ) != 0 )
238 memcpy( p
, iv
, MBEDTLS_CTR_DRBG_BLOCKSIZE
);
239 p
+= MBEDTLS_CTR_DRBG_BLOCKSIZE
;
242 mbedtls_aes_free( &aes_ctx
);
246 mbedtls_platform_zeroize( buf
, sizeof( buf
) );
247 mbedtls_platform_zeroize( tmp
, sizeof( tmp
) );
248 mbedtls_platform_zeroize( key
, sizeof( key
) );
249 mbedtls_platform_zeroize( chain
, sizeof( chain
) );
253 * wipe partial seed from memory
255 mbedtls_platform_zeroize( output
, MBEDTLS_CTR_DRBG_SEEDLEN
);
261 static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context
*ctx
,
262 const unsigned char data
[MBEDTLS_CTR_DRBG_SEEDLEN
] )
264 unsigned char tmp
[MBEDTLS_CTR_DRBG_SEEDLEN
];
265 unsigned char *p
= tmp
;
269 memset( tmp
, 0, MBEDTLS_CTR_DRBG_SEEDLEN
);
271 for( j
= 0; j
< MBEDTLS_CTR_DRBG_SEEDLEN
; j
+= MBEDTLS_CTR_DRBG_BLOCKSIZE
)
276 for( i
= MBEDTLS_CTR_DRBG_BLOCKSIZE
; i
> 0; i
-- )
277 if( ++ctx
->counter
[i
- 1] != 0 )
281 * Crypt counter block
283 if( ( ret
= mbedtls_aes_crypt_ecb( &ctx
->aes_ctx
, MBEDTLS_AES_ENCRYPT
, ctx
->counter
, p
) ) != 0 )
288 p
+= MBEDTLS_CTR_DRBG_BLOCKSIZE
;
291 for( i
= 0; i
< MBEDTLS_CTR_DRBG_SEEDLEN
; i
++ )
295 * Update key and counter
297 if( ( ret
= mbedtls_aes_setkey_enc( &ctx
->aes_ctx
, tmp
, MBEDTLS_CTR_DRBG_KEYBITS
) ) != 0 )
301 memcpy( ctx
->counter
, tmp
+ MBEDTLS_CTR_DRBG_KEYSIZE
, MBEDTLS_CTR_DRBG_BLOCKSIZE
);
306 void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context
*ctx
,
307 const unsigned char *additional
, size_t add_len
)
309 unsigned char add_input
[MBEDTLS_CTR_DRBG_SEEDLEN
];
313 /* MAX_INPUT would be more logical here, but we have to match
314 * block_cipher_df()'s limits since we can't propagate errors */
315 if( add_len
> MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
)
316 add_len
= MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
;
318 block_cipher_df( add_input
, additional
, add_len
);
319 ctr_drbg_update_internal( ctx
, add_input
);
323 int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context
*ctx
,
324 const unsigned char *additional
, size_t len
)
326 unsigned char seed
[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
];
330 if( ctx
->entropy_len
> MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
||
331 len
> MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
- ctx
->entropy_len
)
332 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG
);
334 memset( seed
, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
);
337 * Gather entropy_len bytes of entropy to seed state
339 if( 0 != ctx
->f_entropy( ctx
->p_entropy
, seed
,
342 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED
);
345 seedlen
+= ctx
->entropy_len
;
348 * Add additional data
350 if( additional
&& len
)
352 memcpy( seed
+ seedlen
, additional
, len
);
359 if( ( ret
= block_cipher_df( seed
, seed
, seedlen
) ) != 0 )
367 if( ( ret
= ctr_drbg_update_internal( ctx
, seed
) ) != 0 )
371 ctx
->reseed_counter
= 1;
376 int mbedtls_ctr_drbg_random_with_add( void *p_rng
,
377 unsigned char *output
, size_t output_len
,
378 const unsigned char *additional
, size_t add_len
)
381 mbedtls_ctr_drbg_context
*ctx
= (mbedtls_ctr_drbg_context
*) p_rng
;
382 unsigned char add_input
[MBEDTLS_CTR_DRBG_SEEDLEN
];
383 unsigned char *p
= output
;
384 unsigned char tmp
[MBEDTLS_CTR_DRBG_BLOCKSIZE
];
388 if( output_len
> MBEDTLS_CTR_DRBG_MAX_REQUEST
)
389 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG
);
391 if( add_len
> MBEDTLS_CTR_DRBG_MAX_INPUT
)
392 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG
);
394 memset( add_input
, 0, MBEDTLS_CTR_DRBG_SEEDLEN
);
396 if( ctx
->reseed_counter
> ctx
->reseed_interval
||
397 ctx
->prediction_resistance
)
399 if( ( ret
= mbedtls_ctr_drbg_reseed( ctx
, additional
, add_len
) ) != 0 )
408 if( ( ret
= block_cipher_df( add_input
, additional
, add_len
) ) != 0 )
412 if( ( ret
= ctr_drbg_update_internal( ctx
, add_input
) ) != 0 )
418 while( output_len
> 0 )
423 for( i
= MBEDTLS_CTR_DRBG_BLOCKSIZE
; i
> 0; i
-- )
424 if( ++ctx
->counter
[i
- 1] != 0 )
428 * Crypt counter block
430 if( ( ret
= mbedtls_aes_crypt_ecb( &ctx
->aes_ctx
, MBEDTLS_AES_ENCRYPT
, ctx
->counter
, tmp
) ) != 0 )
435 use_len
= ( output_len
> MBEDTLS_CTR_DRBG_BLOCKSIZE
) ? MBEDTLS_CTR_DRBG_BLOCKSIZE
:
438 * Copy random block to destination
440 memcpy( p
, tmp
, use_len
);
442 output_len
-= use_len
;
445 if( ( ret
= ctr_drbg_update_internal( ctx
, add_input
) ) != 0 )
450 ctx
->reseed_counter
++;
455 int mbedtls_ctr_drbg_random( void *p_rng
, unsigned char *output
, size_t output_len
)
458 mbedtls_ctr_drbg_context
*ctx
= (mbedtls_ctr_drbg_context
*) p_rng
;
460 #if defined(MBEDTLS_THREADING_C)
461 if( ( ret
= mbedtls_mutex_lock( &ctx
->mutex
) ) != 0 )
465 ret
= mbedtls_ctr_drbg_random_with_add( ctx
, output
, output_len
, NULL
, 0 );
467 #if defined(MBEDTLS_THREADING_C)
468 if( mbedtls_mutex_unlock( &ctx
->mutex
) != 0 )
469 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR
);
475 #if defined(MBEDTLS_FS_IO)
476 int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context
*ctx
, const char *path
)
478 int ret
= MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR
;
480 unsigned char buf
[ MBEDTLS_CTR_DRBG_MAX_INPUT
];
482 if( ( f
= fopen( path
, "wb" ) ) == NULL
)
483 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR
);
485 if( ( ret
= mbedtls_ctr_drbg_random( ctx
, buf
, MBEDTLS_CTR_DRBG_MAX_INPUT
) ) != 0 )
488 if( fwrite( buf
, 1, MBEDTLS_CTR_DRBG_MAX_INPUT
, f
) != MBEDTLS_CTR_DRBG_MAX_INPUT
)
489 ret
= MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR
;
494 mbedtls_platform_zeroize( buf
, sizeof( buf
) );
500 int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context
*ctx
, const char *path
)
505 unsigned char buf
[ MBEDTLS_CTR_DRBG_MAX_INPUT
];
507 if( ( f
= fopen( path
, "rb" ) ) == NULL
)
508 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR
);
510 fseek( f
, 0, SEEK_END
);
511 n
= (size_t) ftell( f
);
512 fseek( f
, 0, SEEK_SET
);
514 if( n
> MBEDTLS_CTR_DRBG_MAX_INPUT
)
517 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG
);
520 if( fread( buf
, 1, n
, f
) != n
)
521 ret
= MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR
;
523 mbedtls_ctr_drbg_update( ctx
, buf
, n
);
527 mbedtls_platform_zeroize( buf
, sizeof( buf
) );
532 return( mbedtls_ctr_drbg_write_seed_file( ctx
, path
) );
534 #endif /* MBEDTLS_FS_IO */
536 #if defined(MBEDTLS_SELF_TEST)
538 static const unsigned char entropy_source_pr
[96] =
539 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
540 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
541 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
542 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
543 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
544 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
545 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
546 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
547 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
548 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
549 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
550 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
552 static const unsigned char entropy_source_nopr
[64] =
553 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
554 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
555 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
556 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
557 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
558 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
559 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
560 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
562 static const unsigned char nonce_pers_pr
[16] =
563 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
564 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
566 static const unsigned char nonce_pers_nopr
[16] =
567 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
568 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
570 static const unsigned char result_pr
[16] =
571 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
572 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
574 static const unsigned char result_nopr
[16] =
575 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
576 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
578 static size_t test_offset
;
579 static int ctr_drbg_self_test_entropy( void *data
, unsigned char *buf
,
582 const unsigned char *p
= data
;
583 memcpy( buf
, p
+ test_offset
, len
);
588 #define CHK( c ) if( (c) != 0 ) \
591 mbedtls_printf( "failed\n" ); \
598 int mbedtls_ctr_drbg_self_test( int verbose
)
600 mbedtls_ctr_drbg_context ctx
;
601 unsigned char buf
[16];
603 mbedtls_ctr_drbg_init( &ctx
);
606 * Based on a NIST CTR_DRBG test vector (PR = True)
609 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
612 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx
, ctr_drbg_self_test_entropy
,
613 (void *) entropy_source_pr
, nonce_pers_pr
, 16, 32 ) );
614 mbedtls_ctr_drbg_set_prediction_resistance( &ctx
, MBEDTLS_CTR_DRBG_PR_ON
);
615 CHK( mbedtls_ctr_drbg_random( &ctx
, buf
, MBEDTLS_CTR_DRBG_BLOCKSIZE
) );
616 CHK( mbedtls_ctr_drbg_random( &ctx
, buf
, MBEDTLS_CTR_DRBG_BLOCKSIZE
) );
617 CHK( memcmp( buf
, result_pr
, MBEDTLS_CTR_DRBG_BLOCKSIZE
) );
619 mbedtls_ctr_drbg_free( &ctx
);
622 mbedtls_printf( "passed\n" );
625 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
628 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
630 mbedtls_ctr_drbg_init( &ctx
);
633 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx
, ctr_drbg_self_test_entropy
,
634 (void *) entropy_source_nopr
, nonce_pers_nopr
, 16, 32 ) );
635 CHK( mbedtls_ctr_drbg_random( &ctx
, buf
, 16 ) );
636 CHK( mbedtls_ctr_drbg_reseed( &ctx
, NULL
, 0 ) );
637 CHK( mbedtls_ctr_drbg_random( &ctx
, buf
, 16 ) );
638 CHK( memcmp( buf
, result_nopr
, 16 ) );
640 mbedtls_ctr_drbg_free( &ctx
);
643 mbedtls_printf( "passed\n" );
646 mbedtls_printf( "\n" );
650 #endif /* MBEDTLS_SELF_TEST */
652 #endif /* MBEDTLS_CTR_DRBG_C */