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: 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)
22 * The NIST SP 800-90 DRBGs are described in the following publucation.
24 * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
27 #if !defined(MBEDTLS_CONFIG_FILE)
28 #include "mbedtls/config.h"
30 #include MBEDTLS_CONFIG_FILE
33 #if defined(MBEDTLS_CTR_DRBG_C)
35 #include "mbedtls/ctr_drbg.h"
39 #if defined(MBEDTLS_FS_IO)
43 #if defined(MBEDTLS_SELF_TEST)
44 #if defined(MBEDTLS_PLATFORM_C)
45 #include "mbedtls/platform.h"
48 #define mbedtls_printf printf
49 #endif /* MBEDTLS_PLATFORM_C */
50 #endif /* MBEDTLS_SELF_TEST */
52 /* Implementation that should never be optimized out by the compiler */
53 static void mbedtls_zeroize( void *v
, size_t n
) {
54 volatile unsigned char *p
= v
; while( n
-- ) *p
++ = 0;
58 * CTR_DRBG context initialization
60 void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context
*ctx
)
62 memset( ctx
, 0, sizeof( mbedtls_ctr_drbg_context
) );
64 #if defined(MBEDTLS_THREADING_C)
65 mbedtls_mutex_init( &ctx
->mutex
);
70 * Non-public function wrapped by ctr_crbg_init(). Necessary to allow NIST
71 * tests to succeed (which require known length fixed entropy)
73 int mbedtls_ctr_drbg_seed_entropy_len(
74 mbedtls_ctr_drbg_context
*ctx
,
75 int (*f_entropy
)(void *, unsigned char *, size_t),
77 const unsigned char *custom
,
82 unsigned char key
[MBEDTLS_CTR_DRBG_KEYSIZE
];
84 memset( key
, 0, MBEDTLS_CTR_DRBG_KEYSIZE
);
86 mbedtls_aes_init( &ctx
->aes_ctx
);
88 ctx
->f_entropy
= f_entropy
;
89 ctx
->p_entropy
= p_entropy
;
91 ctx
->entropy_len
= entropy_len
;
92 ctx
->reseed_interval
= MBEDTLS_CTR_DRBG_RESEED_INTERVAL
;
95 * Initialize with an empty key
97 mbedtls_aes_setkey_enc( &ctx
->aes_ctx
, key
, MBEDTLS_CTR_DRBG_KEYBITS
);
99 if( ( ret
= mbedtls_ctr_drbg_reseed( ctx
, custom
, len
) ) != 0 )
105 int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context
*ctx
,
106 int (*f_entropy
)(void *, unsigned char *, size_t),
108 const unsigned char *custom
,
111 return( mbedtls_ctr_drbg_seed_entropy_len( ctx
, f_entropy
, p_entropy
, custom
, len
,
112 MBEDTLS_CTR_DRBG_ENTROPY_LEN
) );
115 void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context
*ctx
)
120 #if defined(MBEDTLS_THREADING_C)
121 mbedtls_mutex_free( &ctx
->mutex
);
123 mbedtls_aes_free( &ctx
->aes_ctx
);
124 mbedtls_zeroize( ctx
, sizeof( mbedtls_ctr_drbg_context
) );
127 void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context
*ctx
, int resistance
)
129 ctx
->prediction_resistance
= resistance
;
132 void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context
*ctx
, size_t len
)
134 ctx
->entropy_len
= len
;
137 void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context
*ctx
, int interval
)
139 ctx
->reseed_interval
= interval
;
142 static int block_cipher_df( unsigned char *output
,
143 const unsigned char *data
, size_t data_len
)
145 unsigned char buf
[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
+ MBEDTLS_CTR_DRBG_BLOCKSIZE
+ 16];
146 unsigned char tmp
[MBEDTLS_CTR_DRBG_SEEDLEN
];
147 unsigned char key
[MBEDTLS_CTR_DRBG_KEYSIZE
];
148 unsigned char chain
[MBEDTLS_CTR_DRBG_BLOCKSIZE
];
149 unsigned char *p
, *iv
;
150 mbedtls_aes_context aes_ctx
;
153 size_t buf_len
, use_len
;
155 if( data_len
> MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
)
156 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG
);
158 memset( buf
, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
+ MBEDTLS_CTR_DRBG_BLOCKSIZE
+ 16 );
159 mbedtls_aes_init( &aes_ctx
);
162 * Construct IV (16 bytes) and S in buffer
163 * IV = Counter (in 32-bits) padded to 16 with zeroes
164 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
166 * (Total is padded to a multiple of 16-bytes with zeroes)
168 p
= buf
+ MBEDTLS_CTR_DRBG_BLOCKSIZE
;
169 *p
++ = ( data_len
>> 24 ) & 0xff;
170 *p
++ = ( data_len
>> 16 ) & 0xff;
171 *p
++ = ( data_len
>> 8 ) & 0xff;
172 *p
++ = ( data_len
) & 0xff;
174 *p
++ = MBEDTLS_CTR_DRBG_SEEDLEN
;
175 memcpy( p
, data
, data_len
);
178 buf_len
= MBEDTLS_CTR_DRBG_BLOCKSIZE
+ 8 + data_len
+ 1;
180 for( i
= 0; i
< MBEDTLS_CTR_DRBG_KEYSIZE
; i
++ )
183 mbedtls_aes_setkey_enc( &aes_ctx
, key
, MBEDTLS_CTR_DRBG_KEYBITS
);
186 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
188 for( j
= 0; j
< MBEDTLS_CTR_DRBG_SEEDLEN
; j
+= MBEDTLS_CTR_DRBG_BLOCKSIZE
)
191 memset( chain
, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE
);
196 for( i
= 0; i
< MBEDTLS_CTR_DRBG_BLOCKSIZE
; i
++ )
198 p
+= MBEDTLS_CTR_DRBG_BLOCKSIZE
;
199 use_len
-= ( use_len
>= MBEDTLS_CTR_DRBG_BLOCKSIZE
) ?
200 MBEDTLS_CTR_DRBG_BLOCKSIZE
: use_len
;
202 mbedtls_aes_crypt_ecb( &aes_ctx
, MBEDTLS_AES_ENCRYPT
, chain
, chain
);
205 memcpy( tmp
+ j
, chain
, MBEDTLS_CTR_DRBG_BLOCKSIZE
);
214 * Do final encryption with reduced data
216 mbedtls_aes_setkey_enc( &aes_ctx
, tmp
, MBEDTLS_CTR_DRBG_KEYBITS
);
217 iv
= tmp
+ MBEDTLS_CTR_DRBG_KEYSIZE
;
220 for( j
= 0; j
< MBEDTLS_CTR_DRBG_SEEDLEN
; j
+= MBEDTLS_CTR_DRBG_BLOCKSIZE
)
222 mbedtls_aes_crypt_ecb( &aes_ctx
, MBEDTLS_AES_ENCRYPT
, iv
, iv
);
223 memcpy( p
, iv
, MBEDTLS_CTR_DRBG_BLOCKSIZE
);
224 p
+= MBEDTLS_CTR_DRBG_BLOCKSIZE
;
227 mbedtls_aes_free( &aes_ctx
);
232 static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context
*ctx
,
233 const unsigned char data
[MBEDTLS_CTR_DRBG_SEEDLEN
] )
235 unsigned char tmp
[MBEDTLS_CTR_DRBG_SEEDLEN
];
236 unsigned char *p
= tmp
;
239 memset( tmp
, 0, MBEDTLS_CTR_DRBG_SEEDLEN
);
241 for( j
= 0; j
< MBEDTLS_CTR_DRBG_SEEDLEN
; j
+= MBEDTLS_CTR_DRBG_BLOCKSIZE
)
246 for( i
= MBEDTLS_CTR_DRBG_BLOCKSIZE
; i
> 0; i
-- )
247 if( ++ctx
->counter
[i
- 1] != 0 )
251 * Crypt counter block
253 mbedtls_aes_crypt_ecb( &ctx
->aes_ctx
, MBEDTLS_AES_ENCRYPT
, ctx
->counter
, p
);
255 p
+= MBEDTLS_CTR_DRBG_BLOCKSIZE
;
258 for( i
= 0; i
< MBEDTLS_CTR_DRBG_SEEDLEN
; i
++ )
262 * Update key and counter
264 mbedtls_aes_setkey_enc( &ctx
->aes_ctx
, tmp
, MBEDTLS_CTR_DRBG_KEYBITS
);
265 memcpy( ctx
->counter
, tmp
+ MBEDTLS_CTR_DRBG_KEYSIZE
, MBEDTLS_CTR_DRBG_BLOCKSIZE
);
270 void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context
*ctx
,
271 const unsigned char *additional
, size_t add_len
)
273 unsigned char add_input
[MBEDTLS_CTR_DRBG_SEEDLEN
];
277 /* MAX_INPUT would be more logical here, but we have to match
278 * block_cipher_df()'s limits since we can't propagate errors */
279 if( add_len
> MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
)
280 add_len
= MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
;
282 block_cipher_df( add_input
, additional
, add_len
);
283 ctr_drbg_update_internal( ctx
, add_input
);
287 int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context
*ctx
,
288 const unsigned char *additional
, size_t len
)
290 unsigned char seed
[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
];
293 if( ctx
->entropy_len
+ len
> MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
)
294 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG
);
296 memset( seed
, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
);
299 * Gather entropy_len bytes of entropy to seed state
301 if( 0 != ctx
->f_entropy( ctx
->p_entropy
, seed
,
304 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED
);
307 seedlen
+= ctx
->entropy_len
;
310 * Add additional data
312 if( additional
&& len
)
314 memcpy( seed
+ seedlen
, additional
, len
);
321 block_cipher_df( seed
, seed
, seedlen
);
326 ctr_drbg_update_internal( ctx
, seed
);
327 ctx
->reseed_counter
= 1;
332 int mbedtls_ctr_drbg_random_with_add( void *p_rng
,
333 unsigned char *output
, size_t output_len
,
334 const unsigned char *additional
, size_t add_len
)
337 mbedtls_ctr_drbg_context
*ctx
= (mbedtls_ctr_drbg_context
*) p_rng
;
338 unsigned char add_input
[MBEDTLS_CTR_DRBG_SEEDLEN
];
339 unsigned char *p
= output
;
340 unsigned char tmp
[MBEDTLS_CTR_DRBG_BLOCKSIZE
];
344 if( output_len
> MBEDTLS_CTR_DRBG_MAX_REQUEST
)
345 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG
);
347 if( add_len
> MBEDTLS_CTR_DRBG_MAX_INPUT
)
348 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG
);
350 memset( add_input
, 0, MBEDTLS_CTR_DRBG_SEEDLEN
);
352 if( ctx
->reseed_counter
> ctx
->reseed_interval
||
353 ctx
->prediction_resistance
)
355 if( ( ret
= mbedtls_ctr_drbg_reseed( ctx
, additional
, add_len
) ) != 0 )
363 block_cipher_df( add_input
, additional
, add_len
);
364 ctr_drbg_update_internal( ctx
, add_input
);
367 while( output_len
> 0 )
372 for( i
= MBEDTLS_CTR_DRBG_BLOCKSIZE
; i
> 0; i
-- )
373 if( ++ctx
->counter
[i
- 1] != 0 )
377 * Crypt counter block
379 mbedtls_aes_crypt_ecb( &ctx
->aes_ctx
, MBEDTLS_AES_ENCRYPT
, ctx
->counter
, tmp
);
381 use_len
= ( output_len
> MBEDTLS_CTR_DRBG_BLOCKSIZE
) ? MBEDTLS_CTR_DRBG_BLOCKSIZE
:
384 * Copy random block to destination
386 memcpy( p
, tmp
, use_len
);
388 output_len
-= use_len
;
391 ctr_drbg_update_internal( ctx
, add_input
);
393 ctx
->reseed_counter
++;
398 int mbedtls_ctr_drbg_random( void *p_rng
, unsigned char *output
, size_t output_len
)
401 mbedtls_ctr_drbg_context
*ctx
= (mbedtls_ctr_drbg_context
*) p_rng
;
403 #if defined(MBEDTLS_THREADING_C)
404 if( ( ret
= mbedtls_mutex_lock( &ctx
->mutex
) ) != 0 )
408 ret
= mbedtls_ctr_drbg_random_with_add( ctx
, output
, output_len
, NULL
, 0 );
410 #if defined(MBEDTLS_THREADING_C)
411 if( mbedtls_mutex_unlock( &ctx
->mutex
) != 0 )
412 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR
);
418 #if defined(MBEDTLS_FS_IO)
419 int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context
*ctx
, const char *path
)
421 int ret
= MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR
;
423 unsigned char buf
[ MBEDTLS_CTR_DRBG_MAX_INPUT
];
425 if( ( f
= fopen( path
, "wb" ) ) == NULL
)
426 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR
);
428 if( ( ret
= mbedtls_ctr_drbg_random( ctx
, buf
, MBEDTLS_CTR_DRBG_MAX_INPUT
) ) != 0 )
431 if( fwrite( buf
, 1, MBEDTLS_CTR_DRBG_MAX_INPUT
, f
) != MBEDTLS_CTR_DRBG_MAX_INPUT
)
433 ret
= MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR
;
444 int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context
*ctx
, const char *path
)
448 unsigned char buf
[ MBEDTLS_CTR_DRBG_MAX_INPUT
];
450 if( ( f
= fopen( path
, "rb" ) ) == NULL
)
451 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR
);
453 fseek( f
, 0, SEEK_END
);
454 n
= (size_t) ftell( f
);
455 fseek( f
, 0, SEEK_SET
);
457 if( n
> MBEDTLS_CTR_DRBG_MAX_INPUT
)
460 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG
);
463 if( fread( buf
, 1, n
, f
) != n
)
466 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR
);
471 mbedtls_ctr_drbg_update( ctx
, buf
, n
);
473 return( mbedtls_ctr_drbg_write_seed_file( ctx
, path
) );
475 #endif /* MBEDTLS_FS_IO */
477 #if defined(MBEDTLS_SELF_TEST)
479 static const unsigned char entropy_source_pr
[96] =
480 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
481 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
482 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
483 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
484 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
485 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
486 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
487 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
488 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
489 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
490 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
491 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
493 static const unsigned char entropy_source_nopr
[64] =
494 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
495 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
496 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
497 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
498 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
499 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
500 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
501 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
503 static const unsigned char nonce_pers_pr
[16] =
504 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
505 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
507 static const unsigned char nonce_pers_nopr
[16] =
508 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
509 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
511 static const unsigned char result_pr
[16] =
512 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
513 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
515 static const unsigned char result_nopr
[16] =
516 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
517 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
519 static size_t test_offset
;
520 static int ctr_drbg_self_test_entropy( void *data
, unsigned char *buf
,
523 const unsigned char *p
= data
;
524 memcpy( buf
, p
+ test_offset
, len
);
529 #define CHK( c ) if( (c) != 0 ) \
532 mbedtls_printf( "failed\n" ); \
539 int mbedtls_ctr_drbg_self_test( int verbose
)
541 mbedtls_ctr_drbg_context ctx
;
542 unsigned char buf
[16];
544 mbedtls_ctr_drbg_init( &ctx
);
547 * Based on a NIST CTR_DRBG test vector (PR = True)
550 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
553 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx
, ctr_drbg_self_test_entropy
,
554 (void *) entropy_source_pr
, nonce_pers_pr
, 16, 32 ) );
555 mbedtls_ctr_drbg_set_prediction_resistance( &ctx
, MBEDTLS_CTR_DRBG_PR_ON
);
556 CHK( mbedtls_ctr_drbg_random( &ctx
, buf
, MBEDTLS_CTR_DRBG_BLOCKSIZE
) );
557 CHK( mbedtls_ctr_drbg_random( &ctx
, buf
, MBEDTLS_CTR_DRBG_BLOCKSIZE
) );
558 CHK( memcmp( buf
, result_pr
, MBEDTLS_CTR_DRBG_BLOCKSIZE
) );
560 mbedtls_ctr_drbg_free( &ctx
);
563 mbedtls_printf( "passed\n" );
566 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
569 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
571 mbedtls_ctr_drbg_init( &ctx
);
574 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx
, ctr_drbg_self_test_entropy
,
575 (void *) entropy_source_nopr
, nonce_pers_nopr
, 16, 32 ) );
576 CHK( mbedtls_ctr_drbg_random( &ctx
, buf
, 16 ) );
577 CHK( mbedtls_ctr_drbg_reseed( &ctx
, NULL
, 0 ) );
578 CHK( mbedtls_ctr_drbg_random( &ctx
, buf
, 16 ) );
579 CHK( memcmp( buf
, result_nopr
, 16 ) );
581 mbedtls_ctr_drbg_free( &ctx
);
584 mbedtls_printf( "passed\n" );
587 mbedtls_printf( "\n" );
591 #endif /* MBEDTLS_SELF_TEST */
593 #endif /* MBEDTLS_CTR_DRBG_C */