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 publucation.
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"
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_PLATFORM_C */
52 #endif /* MBEDTLS_SELF_TEST */
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 * CTR_DRBG context initialization
62 void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context
*ctx
)
64 memset( ctx
, 0, sizeof( mbedtls_ctr_drbg_context
) );
66 #if defined(MBEDTLS_THREADING_C)
67 mbedtls_mutex_init( &ctx
->mutex
);
72 * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow
73 * NIST tests to succeed (which require known length fixed entropy)
75 int mbedtls_ctr_drbg_seed_entropy_len(
76 mbedtls_ctr_drbg_context
*ctx
,
77 int (*f_entropy
)(void *, unsigned char *, size_t),
79 const unsigned char *custom
,
84 unsigned char key
[MBEDTLS_CTR_DRBG_KEYSIZE
];
86 memset( key
, 0, MBEDTLS_CTR_DRBG_KEYSIZE
);
88 mbedtls_aes_init( &ctx
->aes_ctx
);
90 ctx
->f_entropy
= f_entropy
;
91 ctx
->p_entropy
= p_entropy
;
93 ctx
->entropy_len
= entropy_len
;
94 ctx
->reseed_interval
= MBEDTLS_CTR_DRBG_RESEED_INTERVAL
;
97 * Initialize with an empty key
99 mbedtls_aes_setkey_enc( &ctx
->aes_ctx
, key
, MBEDTLS_CTR_DRBG_KEYBITS
);
101 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_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
;
155 size_t buf_len
, use_len
;
157 if( data_len
> MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
)
158 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG
);
160 memset( buf
, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
+ MBEDTLS_CTR_DRBG_BLOCKSIZE
+ 16 );
161 mbedtls_aes_init( &aes_ctx
);
164 * Construct IV (16 bytes) and S in buffer
165 * IV = Counter (in 32-bits) padded to 16 with zeroes
166 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
168 * (Total is padded to a multiple of 16-bytes with zeroes)
170 p
= buf
+ MBEDTLS_CTR_DRBG_BLOCKSIZE
;
171 *p
++ = ( data_len
>> 24 ) & 0xff;
172 *p
++ = ( data_len
>> 16 ) & 0xff;
173 *p
++ = ( data_len
>> 8 ) & 0xff;
174 *p
++ = ( data_len
) & 0xff;
176 *p
++ = MBEDTLS_CTR_DRBG_SEEDLEN
;
177 memcpy( p
, data
, data_len
);
180 buf_len
= MBEDTLS_CTR_DRBG_BLOCKSIZE
+ 8 + data_len
+ 1;
182 for( i
= 0; i
< MBEDTLS_CTR_DRBG_KEYSIZE
; i
++ )
185 mbedtls_aes_setkey_enc( &aes_ctx
, key
, MBEDTLS_CTR_DRBG_KEYBITS
);
188 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
190 for( j
= 0; j
< MBEDTLS_CTR_DRBG_SEEDLEN
; j
+= MBEDTLS_CTR_DRBG_BLOCKSIZE
)
193 memset( chain
, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE
);
198 for( i
= 0; i
< MBEDTLS_CTR_DRBG_BLOCKSIZE
; i
++ )
200 p
+= MBEDTLS_CTR_DRBG_BLOCKSIZE
;
201 use_len
-= ( use_len
>= MBEDTLS_CTR_DRBG_BLOCKSIZE
) ?
202 MBEDTLS_CTR_DRBG_BLOCKSIZE
: use_len
;
204 mbedtls_aes_crypt_ecb( &aes_ctx
, MBEDTLS_AES_ENCRYPT
, chain
, chain
);
207 memcpy( tmp
+ j
, chain
, MBEDTLS_CTR_DRBG_BLOCKSIZE
);
216 * Do final encryption with reduced data
218 mbedtls_aes_setkey_enc( &aes_ctx
, tmp
, MBEDTLS_CTR_DRBG_KEYBITS
);
219 iv
= tmp
+ MBEDTLS_CTR_DRBG_KEYSIZE
;
222 for( j
= 0; j
< MBEDTLS_CTR_DRBG_SEEDLEN
; j
+= MBEDTLS_CTR_DRBG_BLOCKSIZE
)
224 mbedtls_aes_crypt_ecb( &aes_ctx
, MBEDTLS_AES_ENCRYPT
, iv
, iv
);
225 memcpy( p
, iv
, MBEDTLS_CTR_DRBG_BLOCKSIZE
);
226 p
+= MBEDTLS_CTR_DRBG_BLOCKSIZE
;
229 mbedtls_aes_free( &aes_ctx
);
234 static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context
*ctx
,
235 const unsigned char data
[MBEDTLS_CTR_DRBG_SEEDLEN
] )
237 unsigned char tmp
[MBEDTLS_CTR_DRBG_SEEDLEN
];
238 unsigned char *p
= tmp
;
241 memset( tmp
, 0, MBEDTLS_CTR_DRBG_SEEDLEN
);
243 for( j
= 0; j
< MBEDTLS_CTR_DRBG_SEEDLEN
; j
+= MBEDTLS_CTR_DRBG_BLOCKSIZE
)
248 for( i
= MBEDTLS_CTR_DRBG_BLOCKSIZE
; i
> 0; i
-- )
249 if( ++ctx
->counter
[i
- 1] != 0 )
253 * Crypt counter block
255 mbedtls_aes_crypt_ecb( &ctx
->aes_ctx
, MBEDTLS_AES_ENCRYPT
, ctx
->counter
, p
);
257 p
+= MBEDTLS_CTR_DRBG_BLOCKSIZE
;
260 for( i
= 0; i
< MBEDTLS_CTR_DRBG_SEEDLEN
; i
++ )
264 * Update key and counter
266 mbedtls_aes_setkey_enc( &ctx
->aes_ctx
, tmp
, MBEDTLS_CTR_DRBG_KEYBITS
);
267 memcpy( ctx
->counter
, tmp
+ MBEDTLS_CTR_DRBG_KEYSIZE
, MBEDTLS_CTR_DRBG_BLOCKSIZE
);
272 void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context
*ctx
,
273 const unsigned char *additional
, size_t add_len
)
275 unsigned char add_input
[MBEDTLS_CTR_DRBG_SEEDLEN
];
279 /* MAX_INPUT would be more logical here, but we have to match
280 * block_cipher_df()'s limits since we can't propagate errors */
281 if( add_len
> MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
)
282 add_len
= MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
;
284 block_cipher_df( add_input
, additional
, add_len
);
285 ctr_drbg_update_internal( ctx
, add_input
);
289 int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context
*ctx
,
290 const unsigned char *additional
, size_t len
)
292 unsigned char seed
[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
];
295 if( ctx
->entropy_len
+ len
> MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
)
296 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG
);
298 memset( seed
, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
);
301 * Gather entropy_len bytes of entropy to seed state
303 if( 0 != ctx
->f_entropy( ctx
->p_entropy
, seed
,
306 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED
);
309 seedlen
+= ctx
->entropy_len
;
312 * Add additional data
314 if( additional
&& len
)
316 memcpy( seed
+ seedlen
, additional
, len
);
323 block_cipher_df( seed
, seed
, seedlen
);
328 ctr_drbg_update_internal( ctx
, seed
);
329 ctx
->reseed_counter
= 1;
334 int mbedtls_ctr_drbg_random_with_add( void *p_rng
,
335 unsigned char *output
, size_t output_len
,
336 const unsigned char *additional
, size_t add_len
)
339 mbedtls_ctr_drbg_context
*ctx
= (mbedtls_ctr_drbg_context
*) p_rng
;
340 unsigned char add_input
[MBEDTLS_CTR_DRBG_SEEDLEN
];
341 unsigned char *p
= output
;
342 unsigned char tmp
[MBEDTLS_CTR_DRBG_BLOCKSIZE
];
346 if( output_len
> MBEDTLS_CTR_DRBG_MAX_REQUEST
)
347 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG
);
349 if( add_len
> MBEDTLS_CTR_DRBG_MAX_INPUT
)
350 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG
);
352 memset( add_input
, 0, MBEDTLS_CTR_DRBG_SEEDLEN
);
354 if( ctx
->reseed_counter
> ctx
->reseed_interval
||
355 ctx
->prediction_resistance
)
357 if( ( ret
= mbedtls_ctr_drbg_reseed( ctx
, additional
, add_len
) ) != 0 )
365 block_cipher_df( add_input
, additional
, add_len
);
366 ctr_drbg_update_internal( ctx
, add_input
);
369 while( output_len
> 0 )
374 for( i
= MBEDTLS_CTR_DRBG_BLOCKSIZE
; i
> 0; i
-- )
375 if( ++ctx
->counter
[i
- 1] != 0 )
379 * Crypt counter block
381 mbedtls_aes_crypt_ecb( &ctx
->aes_ctx
, MBEDTLS_AES_ENCRYPT
, ctx
->counter
, tmp
);
383 use_len
= ( output_len
> MBEDTLS_CTR_DRBG_BLOCKSIZE
) ? MBEDTLS_CTR_DRBG_BLOCKSIZE
:
386 * Copy random block to destination
388 memcpy( p
, tmp
, use_len
);
390 output_len
-= use_len
;
393 ctr_drbg_update_internal( ctx
, add_input
);
395 ctx
->reseed_counter
++;
400 int mbedtls_ctr_drbg_random( void *p_rng
, unsigned char *output
, size_t output_len
)
403 mbedtls_ctr_drbg_context
*ctx
= (mbedtls_ctr_drbg_context
*) p_rng
;
405 #if defined(MBEDTLS_THREADING_C)
406 if( ( ret
= mbedtls_mutex_lock( &ctx
->mutex
) ) != 0 )
410 ret
= mbedtls_ctr_drbg_random_with_add( ctx
, output
, output_len
, NULL
, 0 );
412 #if defined(MBEDTLS_THREADING_C)
413 if( mbedtls_mutex_unlock( &ctx
->mutex
) != 0 )
414 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR
);
420 #if defined(MBEDTLS_FS_IO)
421 int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context
*ctx
, const char *path
)
423 int ret
= MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR
;
425 unsigned char buf
[ MBEDTLS_CTR_DRBG_MAX_INPUT
];
427 if( ( f
= fopen( path
, "wb" ) ) == NULL
)
428 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR
);
430 if( ( ret
= mbedtls_ctr_drbg_random( ctx
, buf
, MBEDTLS_CTR_DRBG_MAX_INPUT
) ) != 0 )
433 if( fwrite( buf
, 1, MBEDTLS_CTR_DRBG_MAX_INPUT
, f
) != MBEDTLS_CTR_DRBG_MAX_INPUT
)
435 ret
= MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR
;
446 int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context
*ctx
, const char *path
)
450 unsigned char buf
[ MBEDTLS_CTR_DRBG_MAX_INPUT
];
452 if( ( f
= fopen( path
, "rb" ) ) == NULL
)
453 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR
);
455 fseek( f
, 0, SEEK_END
);
456 n
= (size_t) ftell( f
);
457 fseek( f
, 0, SEEK_SET
);
459 if( n
> MBEDTLS_CTR_DRBG_MAX_INPUT
)
462 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG
);
465 if( fread( buf
, 1, n
, f
) != n
)
468 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR
);
473 mbedtls_ctr_drbg_update( ctx
, buf
, n
);
475 return( mbedtls_ctr_drbg_write_seed_file( ctx
, path
) );
477 #endif /* MBEDTLS_FS_IO */
479 #if defined(MBEDTLS_SELF_TEST)
481 static const unsigned char entropy_source_pr
[96] =
482 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
483 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
484 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
485 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
486 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
487 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
488 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
489 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
490 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
491 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
492 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
493 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
495 static const unsigned char entropy_source_nopr
[64] =
496 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
497 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
498 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
499 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
500 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
501 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
502 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
503 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
505 static const unsigned char nonce_pers_pr
[16] =
506 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
507 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
509 static const unsigned char nonce_pers_nopr
[16] =
510 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
511 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
513 static const unsigned char result_pr
[16] =
514 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
515 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
517 static const unsigned char result_nopr
[16] =
518 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
519 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
521 static size_t test_offset
;
522 static int ctr_drbg_self_test_entropy( void *data
, unsigned char *buf
,
525 const unsigned char *p
= data
;
526 memcpy( buf
, p
+ test_offset
, len
);
531 #define CHK( c ) if( (c) != 0 ) \
534 mbedtls_printf( "failed\n" ); \
541 int mbedtls_ctr_drbg_self_test( int verbose
)
543 mbedtls_ctr_drbg_context ctx
;
544 unsigned char buf
[16];
546 mbedtls_ctr_drbg_init( &ctx
);
549 * Based on a NIST CTR_DRBG test vector (PR = True)
552 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
555 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx
, ctr_drbg_self_test_entropy
,
556 (void *) entropy_source_pr
, nonce_pers_pr
, 16, 32 ) );
557 mbedtls_ctr_drbg_set_prediction_resistance( &ctx
, MBEDTLS_CTR_DRBG_PR_ON
);
558 CHK( mbedtls_ctr_drbg_random( &ctx
, buf
, MBEDTLS_CTR_DRBG_BLOCKSIZE
) );
559 CHK( mbedtls_ctr_drbg_random( &ctx
, buf
, MBEDTLS_CTR_DRBG_BLOCKSIZE
) );
560 CHK( memcmp( buf
, result_pr
, MBEDTLS_CTR_DRBG_BLOCKSIZE
) );
562 mbedtls_ctr_drbg_free( &ctx
);
565 mbedtls_printf( "passed\n" );
568 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
571 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
573 mbedtls_ctr_drbg_init( &ctx
);
576 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx
, ctr_drbg_self_test_entropy
,
577 (void *) entropy_source_nopr
, nonce_pers_nopr
, 16, 32 ) );
578 CHK( mbedtls_ctr_drbg_random( &ctx
, buf
, 16 ) );
579 CHK( mbedtls_ctr_drbg_reseed( &ctx
, NULL
, 0 ) );
580 CHK( mbedtls_ctr_drbg_random( &ctx
, buf
, 16 ) );
581 CHK( memcmp( buf
, result_nopr
, 16 ) );
583 mbedtls_ctr_drbg_free( &ctx
);
586 mbedtls_printf( "passed\n" );
589 mbedtls_printf( "\n" );
593 #endif /* MBEDTLS_SELF_TEST */
595 #endif /* MBEDTLS_CTR_DRBG_C */