2 * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
\r
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
\r
5 * SPDX-License-Identifier: Apache-2.0
\r
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
\r
8 * not use this file except in compliance with the License.
\r
9 * You may obtain a copy of the License at
\r
11 * http://www.apache.org/licenses/LICENSE-2.0
\r
13 * Unless required by applicable law or agreed to in writing, software
\r
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
\r
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
16 * See the License for the specific language governing permissions and
\r
17 * limitations under the License.
\r
19 * This file is part of mbed TLS (https://tls.mbed.org)
\r
22 * The NIST SP 800-90 DRBGs are described in the following publication.
\r
24 * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
\r
27 #if !defined(MBEDTLS_CONFIG_FILE)
\r
28 #include "mbedtls/config.h"
\r
30 #include MBEDTLS_CONFIG_FILE
\r
33 #if defined(MBEDTLS_CTR_DRBG_C)
\r
35 #include "mbedtls/ctr_drbg.h"
\r
36 #include "mbedtls/platform_util.h"
\r
40 #if defined(MBEDTLS_FS_IO)
\r
44 #if defined(MBEDTLS_SELF_TEST)
\r
45 #if defined(MBEDTLS_PLATFORM_C)
\r
46 #include "mbedtls/platform.h"
\r
49 #define mbedtls_printf printf
\r
50 #endif /* MBEDTLS_PLATFORM_C */
\r
51 #endif /* MBEDTLS_SELF_TEST */
\r
54 * CTR_DRBG context initialization
\r
56 void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
\r
58 memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
\r
60 #if defined(MBEDTLS_THREADING_C)
\r
61 mbedtls_mutex_init( &ctx->mutex );
\r
66 * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow
\r
67 * NIST tests to succeed (which require known length fixed entropy)
\r
69 /* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2)
\r
70 * mbedtls_ctr_drbg_seed_entropy_len(ctx, f_entropy, p_entropy,
\r
71 * custom, len, entropy_len)
\r
73 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
\r
74 * security_strength) -> initial_working_state
\r
76 * custom[:len] = nonce || personalization_string
\r
77 * where entropy_input comes from f_entropy for entropy_len bytes
\r
79 * ctx = initial_working_state
\r
81 int mbedtls_ctr_drbg_seed_entropy_len(
\r
82 mbedtls_ctr_drbg_context *ctx,
\r
83 int (*f_entropy)(void *, unsigned char *, size_t),
\r
85 const unsigned char *custom,
\r
87 size_t entropy_len )
\r
90 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
\r
92 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
\r
94 mbedtls_aes_init( &ctx->aes_ctx );
\r
96 ctx->f_entropy = f_entropy;
\r
97 ctx->p_entropy = p_entropy;
\r
99 ctx->entropy_len = entropy_len;
\r
100 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
\r
103 * Initialize with an empty key
\r
105 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
\r
106 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
\r
111 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
\r
118 int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
\r
119 int (*f_entropy)(void *, unsigned char *, size_t),
\r
121 const unsigned char *custom,
\r
124 return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy,
\r
126 MBEDTLS_CTR_DRBG_ENTROPY_LEN ) );
\r
129 void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
\r
134 #if defined(MBEDTLS_THREADING_C)
\r
135 mbedtls_mutex_free( &ctx->mutex );
\r
137 mbedtls_aes_free( &ctx->aes_ctx );
\r
138 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
\r
141 void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx,
\r
144 ctx->prediction_resistance = resistance;
\r
147 void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx,
\r
150 ctx->entropy_len = len;
\r
153 void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx,
\r
156 ctx->reseed_interval = interval;
\r
159 static int block_cipher_df( unsigned char *output,
\r
160 const unsigned char *data, size_t data_len )
\r
162 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
\r
163 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
\r
164 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
\r
165 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
\r
166 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
\r
167 unsigned char *p, *iv;
\r
168 mbedtls_aes_context aes_ctx;
\r
172 size_t buf_len, use_len;
\r
174 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
\r
175 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
\r
177 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
\r
178 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
\r
179 mbedtls_aes_init( &aes_ctx );
\r
182 * Construct IV (16 bytes) and S in buffer
\r
183 * IV = Counter (in 32-bits) padded to 16 with zeroes
\r
184 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
\r
186 * (Total is padded to a multiple of 16-bytes with zeroes)
\r
188 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
\r
189 *p++ = ( data_len >> 24 ) & 0xff;
\r
190 *p++ = ( data_len >> 16 ) & 0xff;
\r
191 *p++ = ( data_len >> 8 ) & 0xff;
\r
192 *p++ = ( data_len ) & 0xff;
\r
194 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
\r
195 memcpy( p, data, data_len );
\r
196 p[data_len] = 0x80;
\r
198 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
\r
200 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
\r
203 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key,
\r
204 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
\r
210 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
\r
212 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
\r
215 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
\r
218 while( use_len > 0 )
\r
220 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
\r
222 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
\r
223 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
\r
224 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
\r
226 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
\r
227 chain, chain ) ) != 0 )
\r
233 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
\r
242 * Do final encryption with reduced data
\r
244 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp,
\r
245 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
\r
249 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
\r
252 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
\r
254 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
\r
259 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
\r
260 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
\r
263 mbedtls_aes_free( &aes_ctx );
\r
265 * tidy up the stack
\r
267 mbedtls_platform_zeroize( buf, sizeof( buf ) );
\r
268 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
\r
269 mbedtls_platform_zeroize( key, sizeof( key ) );
\r
270 mbedtls_platform_zeroize( chain, sizeof( chain ) );
\r
274 * wipe partial seed from memory
\r
276 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
\r
282 /* CTR_DRBG_Update (SP 800-90A §10.2.1.2)
\r
283 * ctr_drbg_update_internal(ctx, provided_data)
\r
285 * CTR_DRBG_Update(provided_data, Key, V)
\r
286 * with inputs and outputs
\r
287 * ctx->aes_ctx = Key
\r
290 static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
\r
291 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
\r
293 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
\r
294 unsigned char *p = tmp;
\r
298 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
\r
300 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
\r
305 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
\r
306 if( ++ctx->counter[i - 1] != 0 )
\r
310 * Crypt counter block
\r
312 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
\r
313 ctx->counter, p ) ) != 0 )
\r
318 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
\r
321 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
\r
325 * Update key and counter
\r
327 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp,
\r
328 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
\r
332 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
\r
333 MBEDTLS_CTR_DRBG_BLOCKSIZE );
\r
336 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
\r
340 /* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2)
\r
341 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
\r
343 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
\r
344 * security_strength) -> initial_working_state
\r
346 * ctx->counter = all-bits-0
\r
347 * ctx->aes_ctx = context from all-bits-0 key
\r
348 * additional[:add_len] = entropy_input || nonce || personalization_string
\r
350 * ctx = initial_working_state
\r
352 int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
\r
353 const unsigned char *additional,
\r
356 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
\r
362 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
\r
364 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
\r
368 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
\r
372 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
\r
373 void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
\r
374 const unsigned char *additional,
\r
377 /* MAX_INPUT would be more logical here, but we have to match
\r
378 * block_cipher_df()'s limits since we can't propagate errors */
\r
379 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
\r
380 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
\r
381 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
\r
383 #endif /* MBEDTLS_DEPRECATED_REMOVED */
\r
385 /* CTR_DRBG_Reseed with derivation function (SP 800-90A §10.2.1.4.2)
\r
386 * mbedtls_ctr_drbg_reseed(ctx, additional, len)
\r
388 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
\r
389 * -> new_working_state
\r
391 * ctx contains working_state
\r
392 * additional[:len] = additional_input
\r
393 * and entropy_input comes from calling ctx->f_entropy
\r
395 * ctx contains new_working_state
\r
397 int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
\r
398 const unsigned char *additional, size_t len )
\r
400 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
\r
401 size_t seedlen = 0;
\r
404 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
\r
405 len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
\r
406 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
\r
408 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
\r
411 * Gather entropy_len bytes of entropy to seed state
\r
413 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
\r
414 ctx->entropy_len ) )
\r
416 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
\r
419 seedlen += ctx->entropy_len;
\r
422 * Add additional data
\r
424 if( additional && len )
\r
426 memcpy( seed + seedlen, additional, len );
\r
431 * Reduce to 384 bits
\r
433 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
\r
439 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
\r
441 ctx->reseed_counter = 1;
\r
444 mbedtls_platform_zeroize( seed, sizeof( seed ) );
\r
448 /* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2)
\r
449 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
\r
451 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
\r
452 * -> working_state_after_reseed
\r
453 * if required, then
\r
454 * CTR_DRBG_Generate(working_state_after_reseed,
\r
455 * requested_number_of_bits, additional_input)
\r
456 * -> status, returned_bits, new_working_state
\r
458 * ctx contains working_state
\r
459 * requested_number_of_bits = 8 * output_len
\r
460 * additional[:add_len] = additional_input
\r
461 * and entropy_input comes from calling ctx->f_entropy
\r
463 * status = SUCCESS (this function does the reseed internally)
\r
464 * returned_bits = output[:output_len]
\r
465 * ctx contains new_working_state
\r
467 int mbedtls_ctr_drbg_random_with_add( void *p_rng,
\r
468 unsigned char *output, size_t output_len,
\r
469 const unsigned char *additional, size_t add_len )
\r
472 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
\r
473 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
\r
474 unsigned char *p = output;
\r
475 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
\r
479 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
\r
480 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
\r
482 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
\r
483 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
\r
485 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
\r
487 if( ctx->reseed_counter > ctx->reseed_interval ||
\r
488 ctx->prediction_resistance )
\r
490 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
\r
499 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
\r
501 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
\r
505 while( output_len > 0 )
\r
510 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
\r
511 if( ++ctx->counter[i - 1] != 0 )
\r
515 * Crypt counter block
\r
517 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
\r
518 ctx->counter, tmp ) ) != 0 )
\r
523 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE )
\r
524 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
\r
526 * Copy random block to destination
\r
528 memcpy( p, tmp, use_len );
\r
530 output_len -= use_len;
\r
533 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
\r
536 ctx->reseed_counter++;
\r
539 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
\r
540 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
\r
544 int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output,
\r
545 size_t output_len )
\r
548 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
\r
550 #if defined(MBEDTLS_THREADING_C)
\r
551 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
\r
555 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
\r
557 #if defined(MBEDTLS_THREADING_C)
\r
558 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
\r
559 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
\r
565 #if defined(MBEDTLS_FS_IO)
\r
566 int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx,
\r
569 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
\r
571 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
\r
573 if( ( f = fopen( path, "wb" ) ) == NULL )
\r
574 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
\r
576 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf,
\r
577 MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
\r
580 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) !=
\r
581 MBEDTLS_CTR_DRBG_MAX_INPUT )
\r
583 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
\r
591 mbedtls_platform_zeroize( buf, sizeof( buf ) );
\r
597 int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx,
\r
603 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
\r
606 if( ( f = fopen( path, "rb" ) ) == NULL )
\r
607 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
\r
609 n = fread( buf, 1, sizeof( buf ), f );
\r
610 if( fread( &c, 1, 1, f ) != 0 )
\r
612 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
\r
615 if( n == 0 || ferror( f ) )
\r
617 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
\r
623 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
\r
626 mbedtls_platform_zeroize( buf, sizeof( buf ) );
\r
631 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
\r
633 #endif /* MBEDTLS_FS_IO */
\r
635 #if defined(MBEDTLS_SELF_TEST)
\r
637 static const unsigned char entropy_source_pr[96] =
\r
638 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
\r
639 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
\r
640 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
\r
641 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
\r
642 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
\r
643 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
\r
644 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
\r
645 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
\r
646 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
\r
647 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
\r
648 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
\r
649 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
\r
651 static const unsigned char entropy_source_nopr[64] =
\r
652 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
\r
653 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
\r
654 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
\r
655 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
\r
656 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
\r
657 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
\r
658 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
\r
659 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
\r
661 static const unsigned char nonce_pers_pr[16] =
\r
662 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
\r
663 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
\r
665 static const unsigned char nonce_pers_nopr[16] =
\r
666 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
\r
667 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
\r
669 static const unsigned char result_pr[16] =
\r
670 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
\r
671 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
\r
673 static const unsigned char result_nopr[16] =
\r
674 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
\r
675 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
\r
677 static size_t test_offset;
\r
678 static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
\r
681 const unsigned char *p = data;
\r
682 memcpy( buf, p + test_offset, len );
\r
683 test_offset += len;
\r
687 #define CHK( c ) if( (c) != 0 ) \
\r
689 if( verbose != 0 ) \
\r
690 mbedtls_printf( "failed\n" ); \
\r
697 int mbedtls_ctr_drbg_self_test( int verbose )
\r
699 mbedtls_ctr_drbg_context ctx;
\r
700 unsigned char buf[16];
\r
702 mbedtls_ctr_drbg_init( &ctx );
\r
705 * Based on a NIST CTR_DRBG test vector (PR = True)
\r
708 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
\r
711 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
\r
712 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
\r
713 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
\r
714 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
\r
715 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
\r
716 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
\r
718 mbedtls_ctr_drbg_free( &ctx );
\r
721 mbedtls_printf( "passed\n" );
\r
724 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
\r
727 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
\r
729 mbedtls_ctr_drbg_init( &ctx );
\r
732 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
\r
733 (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
\r
734 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
\r
735 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
\r
736 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
\r
737 CHK( memcmp( buf, result_nopr, 16 ) );
\r
739 mbedtls_ctr_drbg_free( &ctx );
\r
742 mbedtls_printf( "passed\n" );
\r
745 mbedtls_printf( "\n" );
\r
749 #endif /* MBEDTLS_SELF_TEST */
\r
751 #endif /* MBEDTLS_CTR_DRBG_C */
\r