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"
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 if( ( ret
= mbedtls_aes_setkey_enc( &ctx
->aes_ctx
, key
, MBEDTLS_CTR_DRBG_KEYBITS
) ) != 0 )
104 if( ( ret
= mbedtls_ctr_drbg_reseed( ctx
, custom
, len
) ) != 0 )
111 int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context
*ctx
,
112 int (*f_entropy
)(void *, unsigned char *, size_t),
114 const unsigned char *custom
,
117 return( mbedtls_ctr_drbg_seed_entropy_len( ctx
, f_entropy
, p_entropy
, custom
, len
,
118 MBEDTLS_CTR_DRBG_ENTROPY_LEN
) );
121 void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context
*ctx
)
126 #if defined(MBEDTLS_THREADING_C)
127 mbedtls_mutex_free( &ctx
->mutex
);
129 mbedtls_aes_free( &ctx
->aes_ctx
);
130 mbedtls_zeroize( ctx
, sizeof( mbedtls_ctr_drbg_context
) );
133 void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context
*ctx
, int resistance
)
135 ctx
->prediction_resistance
= resistance
;
138 void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context
*ctx
, size_t len
)
140 ctx
->entropy_len
= len
;
143 void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context
*ctx
, int interval
)
145 ctx
->reseed_interval
= interval
;
148 static int block_cipher_df( unsigned char *output
,
149 const unsigned char *data
, size_t data_len
)
151 unsigned char buf
[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
+ MBEDTLS_CTR_DRBG_BLOCKSIZE
+ 16];
152 unsigned char tmp
[MBEDTLS_CTR_DRBG_SEEDLEN
];
153 unsigned char key
[MBEDTLS_CTR_DRBG_KEYSIZE
];
154 unsigned char chain
[MBEDTLS_CTR_DRBG_BLOCKSIZE
];
155 unsigned char *p
, *iv
;
156 mbedtls_aes_context aes_ctx
;
160 size_t buf_len
, use_len
;
162 if( data_len
> MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
)
163 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG
);
165 memset( buf
, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
+ MBEDTLS_CTR_DRBG_BLOCKSIZE
+ 16 );
166 mbedtls_aes_init( &aes_ctx
);
169 * Construct IV (16 bytes) and S in buffer
170 * IV = Counter (in 32-bits) padded to 16 with zeroes
171 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
173 * (Total is padded to a multiple of 16-bytes with zeroes)
175 p
= buf
+ MBEDTLS_CTR_DRBG_BLOCKSIZE
;
176 *p
++ = ( data_len
>> 24 ) & 0xff;
177 *p
++ = ( data_len
>> 16 ) & 0xff;
178 *p
++ = ( data_len
>> 8 ) & 0xff;
179 *p
++ = ( data_len
) & 0xff;
181 *p
++ = MBEDTLS_CTR_DRBG_SEEDLEN
;
182 memcpy( p
, data
, data_len
);
185 buf_len
= MBEDTLS_CTR_DRBG_BLOCKSIZE
+ 8 + data_len
+ 1;
187 for( i
= 0; i
< MBEDTLS_CTR_DRBG_KEYSIZE
; i
++ )
190 if( ( ret
= mbedtls_aes_setkey_enc( &aes_ctx
, key
, MBEDTLS_CTR_DRBG_KEYBITS
) ) != 0 )
196 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
198 for( j
= 0; j
< MBEDTLS_CTR_DRBG_SEEDLEN
; j
+= MBEDTLS_CTR_DRBG_BLOCKSIZE
)
201 memset( chain
, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE
);
206 for( i
= 0; i
< MBEDTLS_CTR_DRBG_BLOCKSIZE
; i
++ )
208 p
+= MBEDTLS_CTR_DRBG_BLOCKSIZE
;
209 use_len
-= ( use_len
>= MBEDTLS_CTR_DRBG_BLOCKSIZE
) ?
210 MBEDTLS_CTR_DRBG_BLOCKSIZE
: use_len
;
212 if( ( ret
= mbedtls_aes_crypt_ecb( &aes_ctx
, MBEDTLS_AES_ENCRYPT
, chain
, chain
) ) != 0 )
218 memcpy( tmp
+ j
, chain
, MBEDTLS_CTR_DRBG_BLOCKSIZE
);
227 * Do final encryption with reduced data
229 if( ( ret
= mbedtls_aes_setkey_enc( &aes_ctx
, tmp
, MBEDTLS_CTR_DRBG_KEYBITS
) ) != 0 )
233 iv
= tmp
+ MBEDTLS_CTR_DRBG_KEYSIZE
;
236 for( j
= 0; j
< MBEDTLS_CTR_DRBG_SEEDLEN
; j
+= MBEDTLS_CTR_DRBG_BLOCKSIZE
)
238 if( ( ret
= mbedtls_aes_crypt_ecb( &aes_ctx
, MBEDTLS_AES_ENCRYPT
, iv
, iv
) ) != 0 )
242 memcpy( p
, iv
, MBEDTLS_CTR_DRBG_BLOCKSIZE
);
243 p
+= MBEDTLS_CTR_DRBG_BLOCKSIZE
;
246 mbedtls_aes_free( &aes_ctx
);
250 mbedtls_zeroize( buf
, sizeof( buf
) );
251 mbedtls_zeroize( tmp
, sizeof( tmp
) );
252 mbedtls_zeroize( key
, sizeof( key
) );
253 mbedtls_zeroize( chain
, sizeof( chain
) );
257 * wipe partial seed from memory
259 mbedtls_zeroize( output
, MBEDTLS_CTR_DRBG_SEEDLEN
);
265 static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context
*ctx
,
266 const unsigned char data
[MBEDTLS_CTR_DRBG_SEEDLEN
] )
268 unsigned char tmp
[MBEDTLS_CTR_DRBG_SEEDLEN
];
269 unsigned char *p
= tmp
;
273 memset( tmp
, 0, MBEDTLS_CTR_DRBG_SEEDLEN
);
275 for( j
= 0; j
< MBEDTLS_CTR_DRBG_SEEDLEN
; j
+= MBEDTLS_CTR_DRBG_BLOCKSIZE
)
280 for( i
= MBEDTLS_CTR_DRBG_BLOCKSIZE
; i
> 0; i
-- )
281 if( ++ctx
->counter
[i
- 1] != 0 )
285 * Crypt counter block
287 if( ( ret
= mbedtls_aes_crypt_ecb( &ctx
->aes_ctx
, MBEDTLS_AES_ENCRYPT
, ctx
->counter
, p
) ) != 0 )
290 p
+= MBEDTLS_CTR_DRBG_BLOCKSIZE
;
293 for( i
= 0; i
< MBEDTLS_CTR_DRBG_SEEDLEN
; i
++ )
297 * Update key and counter
299 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
);
304 mbedtls_zeroize( tmp
, sizeof( tmp
) );
308 int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context
*ctx
,
309 const unsigned char *additional
,
312 unsigned char add_input
[MBEDTLS_CTR_DRBG_SEEDLEN
];
318 if( ( ret
= block_cipher_df( add_input
, additional
, add_len
) ) != 0 )
320 if( ( ret
= ctr_drbg_update_internal( ctx
, add_input
) ) != 0 )
324 mbedtls_zeroize( add_input
, sizeof( add_input
) );
328 /* Deprecated function, kept for backward compatibility. */
329 void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context
*ctx
,
330 const unsigned char *additional
,
333 /* MAX_INPUT would be more logical here, but we have to match
334 * block_cipher_df()'s limits since we can't propagate errors */
335 if( add_len
> MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
)
336 add_len
= MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
;
337 (void) mbedtls_ctr_drbg_update_ret( ctx
, additional
, add_len
);
340 int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context
*ctx
,
341 const unsigned char *additional
, size_t len
)
343 unsigned char seed
[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
];
347 if( ctx
->entropy_len
> MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
||
348 len
> MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
- ctx
->entropy_len
)
349 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG
);
351 memset( seed
, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
);
354 * Gather entropy_len bytes of entropy to seed state
356 if( 0 != ctx
->f_entropy( ctx
->p_entropy
, seed
,
359 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED
);
362 seedlen
+= ctx
->entropy_len
;
365 * Add additional data
367 if( additional
&& len
)
369 memcpy( seed
+ seedlen
, additional
, len
);
376 if( ( ret
= block_cipher_df( seed
, seed
, seedlen
) ) != 0 )
382 if( ( ret
= ctr_drbg_update_internal( ctx
, seed
) ) != 0 )
384 ctx
->reseed_counter
= 1;
387 mbedtls_zeroize( seed
, sizeof( seed
) );
391 int mbedtls_ctr_drbg_random_with_add( void *p_rng
,
392 unsigned char *output
, size_t output_len
,
393 const unsigned char *additional
, size_t add_len
)
396 mbedtls_ctr_drbg_context
*ctx
= (mbedtls_ctr_drbg_context
*) p_rng
;
397 unsigned char add_input
[MBEDTLS_CTR_DRBG_SEEDLEN
];
398 unsigned char *p
= output
;
399 unsigned char tmp
[MBEDTLS_CTR_DRBG_BLOCKSIZE
];
403 if( output_len
> MBEDTLS_CTR_DRBG_MAX_REQUEST
)
404 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG
);
406 if( add_len
> MBEDTLS_CTR_DRBG_MAX_INPUT
)
407 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG
);
409 memset( add_input
, 0, MBEDTLS_CTR_DRBG_SEEDLEN
);
411 if( ctx
->reseed_counter
> ctx
->reseed_interval
||
412 ctx
->prediction_resistance
)
414 if( ( ret
= mbedtls_ctr_drbg_reseed( ctx
, additional
, add_len
) ) != 0 )
423 if( ( ret
= block_cipher_df( add_input
, additional
, add_len
) ) != 0 )
425 if( ( ret
= ctr_drbg_update_internal( ctx
, add_input
) ) != 0 )
429 while( output_len
> 0 )
434 for( i
= MBEDTLS_CTR_DRBG_BLOCKSIZE
; i
> 0; i
-- )
435 if( ++ctx
->counter
[i
- 1] != 0 )
439 * Crypt counter block
441 if( ( ret
= mbedtls_aes_crypt_ecb( &ctx
->aes_ctx
, MBEDTLS_AES_ENCRYPT
, ctx
->counter
, tmp
) ) != 0 )
444 use_len
= ( output_len
> MBEDTLS_CTR_DRBG_BLOCKSIZE
) ? MBEDTLS_CTR_DRBG_BLOCKSIZE
:
447 * Copy random block to destination
449 memcpy( p
, tmp
, use_len
);
451 output_len
-= use_len
;
454 if( ( ret
= ctr_drbg_update_internal( ctx
, add_input
) ) != 0 )
457 ctx
->reseed_counter
++;
460 mbedtls_zeroize( add_input
, sizeof( add_input
) );
461 mbedtls_zeroize( tmp
, sizeof( tmp
) );
465 int mbedtls_ctr_drbg_random( void *p_rng
, unsigned char *output
, size_t output_len
)
468 mbedtls_ctr_drbg_context
*ctx
= (mbedtls_ctr_drbg_context
*) p_rng
;
470 #if defined(MBEDTLS_THREADING_C)
471 if( ( ret
= mbedtls_mutex_lock( &ctx
->mutex
) ) != 0 )
475 ret
= mbedtls_ctr_drbg_random_with_add( ctx
, output
, output_len
, NULL
, 0 );
477 #if defined(MBEDTLS_THREADING_C)
478 if( mbedtls_mutex_unlock( &ctx
->mutex
) != 0 )
479 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR
);
485 #if defined(MBEDTLS_FS_IO)
486 int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context
*ctx
, const char *path
)
488 int ret
= MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR
;
490 unsigned char buf
[ MBEDTLS_CTR_DRBG_MAX_INPUT
];
492 if( ( f
= fopen( path
, "wb" ) ) == NULL
)
493 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR
);
495 if( ( ret
= mbedtls_ctr_drbg_random( ctx
, buf
, MBEDTLS_CTR_DRBG_MAX_INPUT
) ) != 0 )
498 if( fwrite( buf
, 1, MBEDTLS_CTR_DRBG_MAX_INPUT
, f
) != MBEDTLS_CTR_DRBG_MAX_INPUT
)
499 ret
= MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR
;
504 mbedtls_zeroize( buf
, sizeof( buf
) );
510 int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context
*ctx
, const char *path
)
515 unsigned char buf
[ MBEDTLS_CTR_DRBG_MAX_INPUT
];
517 if( ( f
= fopen( path
, "rb" ) ) == NULL
)
518 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR
);
520 fseek( f
, 0, SEEK_END
);
521 n
= (size_t) ftell( f
);
522 fseek( f
, 0, SEEK_SET
);
524 if( n
> MBEDTLS_CTR_DRBG_MAX_INPUT
)
527 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG
);
530 if( fread( buf
, 1, n
, f
) != n
)
531 ret
= MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR
;
533 ret
= mbedtls_ctr_drbg_update_ret( ctx
, buf
, n
);
537 mbedtls_zeroize( buf
, sizeof( buf
) );
542 return( mbedtls_ctr_drbg_write_seed_file( ctx
, path
) );
544 #endif /* MBEDTLS_FS_IO */
546 #if defined(MBEDTLS_SELF_TEST)
548 static const unsigned char entropy_source_pr
[96] =
549 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
550 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
551 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
552 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
553 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
554 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
555 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
556 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
557 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
558 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
559 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
560 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
562 static const unsigned char entropy_source_nopr
[64] =
563 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
564 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
565 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
566 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
567 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
568 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
569 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
570 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
572 static const unsigned char nonce_pers_pr
[16] =
573 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
574 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
576 static const unsigned char nonce_pers_nopr
[16] =
577 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
578 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
580 static const unsigned char result_pr
[16] =
581 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
582 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
584 static const unsigned char result_nopr
[16] =
585 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
586 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
588 static size_t test_offset
;
589 static int ctr_drbg_self_test_entropy( void *data
, unsigned char *buf
,
592 const unsigned char *p
= data
;
593 memcpy( buf
, p
+ test_offset
, len
);
598 #define CHK( c ) if( (c) != 0 ) \
601 mbedtls_printf( "failed\n" ); \
608 int mbedtls_ctr_drbg_self_test( int verbose
)
610 mbedtls_ctr_drbg_context ctx
;
611 unsigned char buf
[16];
613 mbedtls_ctr_drbg_init( &ctx
);
616 * Based on a NIST CTR_DRBG test vector (PR = True)
619 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
622 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx
, ctr_drbg_self_test_entropy
,
623 (void *) entropy_source_pr
, nonce_pers_pr
, 16, 32 ) );
624 mbedtls_ctr_drbg_set_prediction_resistance( &ctx
, MBEDTLS_CTR_DRBG_PR_ON
);
625 CHK( mbedtls_ctr_drbg_random( &ctx
, buf
, MBEDTLS_CTR_DRBG_BLOCKSIZE
) );
626 CHK( mbedtls_ctr_drbg_random( &ctx
, buf
, MBEDTLS_CTR_DRBG_BLOCKSIZE
) );
627 CHK( memcmp( buf
, result_pr
, MBEDTLS_CTR_DRBG_BLOCKSIZE
) );
629 mbedtls_ctr_drbg_free( &ctx
);
632 mbedtls_printf( "passed\n" );
635 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
638 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
640 mbedtls_ctr_drbg_init( &ctx
);
643 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx
, ctr_drbg_self_test_entropy
,
644 (void *) entropy_source_nopr
, nonce_pers_nopr
, 16, 32 ) );
645 CHK( mbedtls_ctr_drbg_random( &ctx
, buf
, 16 ) );
646 CHK( mbedtls_ctr_drbg_reseed( &ctx
, NULL
, 0 ) );
647 CHK( mbedtls_ctr_drbg_random( &ctx
, buf
, 16 ) );
648 CHK( memcmp( buf
, result_nopr
, 16 ) );
650 mbedtls_ctr_drbg_free( &ctx
);
653 mbedtls_printf( "passed\n" );
656 mbedtls_printf( "\n" );
660 #endif /* MBEDTLS_SELF_TEST */
662 #endif /* MBEDTLS_CTR_DRBG_C */