blob: 4127c3c5bef40d9276a302023f15144b7e09ed71 [file] [log] [blame]
Edison Aic6672fd2018-02-28 15:01:47 +08001// SPDX-License-Identifier: Apache-2.0
Jens Wiklander817466c2018-05-22 13:49:31 +02002/*
3 * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
4 *
5 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Jens Wiklander817466c2018-05-22 13:49:31 +02006 *
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
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
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.
18 *
19 * This file is part of mbed TLS (https://tls.mbed.org)
20 */
21/*
22 * The NIST SP 800-90 DRBGs are described in the following publucation.
23 *
24 * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
25 */
26
27#if !defined(MBEDTLS_CONFIG_FILE)
28#include "mbedtls/config.h"
29#else
30#include MBEDTLS_CONFIG_FILE
31#endif
32
33#if defined(MBEDTLS_CTR_DRBG_C)
34
35#include "mbedtls/ctr_drbg.h"
36
37#include <string.h>
38
39#if defined(MBEDTLS_FS_IO)
40#include <stdio.h>
41#endif
42
43#if defined(MBEDTLS_SELF_TEST)
44#if defined(MBEDTLS_PLATFORM_C)
45#include "mbedtls/platform.h"
46#else
47#include <stdio.h>
48#define mbedtls_printf printf
49#endif /* MBEDTLS_PLATFORM_C */
50#endif /* MBEDTLS_SELF_TEST */
51
52/* Implementation that should never be optimized out by the compiler */
53static void mbedtls_zeroize( void *v, size_t n ) {
54 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
55}
56
57/*
58 * CTR_DRBG context initialization
59 */
60void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
61{
62 memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
63
64#if defined(MBEDTLS_THREADING_C)
65 mbedtls_mutex_init( &ctx->mutex );
66#endif
67}
68
69/*
70 * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow
71 * NIST tests to succeed (which require known length fixed entropy)
72 */
73int mbedtls_ctr_drbg_seed_entropy_len(
74 mbedtls_ctr_drbg_context *ctx,
75 int (*f_entropy)(void *, unsigned char *, size_t),
76 void *p_entropy,
77 const unsigned char *custom,
78 size_t len,
79 size_t entropy_len )
80{
81 int ret;
82 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
83
84 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
85
86 mbedtls_aes_init( &ctx->aes_ctx );
87
88 ctx->f_entropy = f_entropy;
89 ctx->p_entropy = p_entropy;
90
91 ctx->entropy_len = entropy_len;
92 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
93
94 /*
95 * Initialize with an empty key
96 */
97 mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS );
98
99 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
100 return( ret );
101
102 return( 0 );
103}
104
105int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
106 int (*f_entropy)(void *, unsigned char *, size_t),
107 void *p_entropy,
108 const unsigned char *custom,
109 size_t len )
110{
111 return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy, custom, len,
112 MBEDTLS_CTR_DRBG_ENTROPY_LEN ) );
113}
114
115void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
116{
117 if( ctx == NULL )
118 return;
119
120#if defined(MBEDTLS_THREADING_C)
121 mbedtls_mutex_free( &ctx->mutex );
122#endif
123 mbedtls_aes_free( &ctx->aes_ctx );
124 mbedtls_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
125}
126
127void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
128{
129 ctx->prediction_resistance = resistance;
130}
131
132void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len )
133{
134 ctx->entropy_len = len;
135}
136
137void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval )
138{
139 ctx->reseed_interval = interval;
140}
141
142static int block_cipher_df( unsigned char *output,
143 const unsigned char *data, size_t data_len )
144{
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;
151
152 int i, j;
153 size_t buf_len, use_len;
154
155 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
156 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
157
158 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
159 mbedtls_aes_init( &aes_ctx );
160
161 /*
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) ||
165 * data || 0x80
166 * (Total is padded to a multiple of 16-bytes with zeroes)
167 */
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;
173 p += 3;
174 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
175 memcpy( p, data, data_len );
176 p[data_len] = 0x80;
177
178 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
179
180 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
181 key[i] = i;
182
183 mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS );
184
185 /*
186 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
187 */
188 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
189 {
190 p = buf;
191 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
192 use_len = buf_len;
193
194 while( use_len > 0 )
195 {
196 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
197 chain[i] ^= p[i];
198 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
199 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
200 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
201
202 mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain );
203 }
204
205 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
206
207 /*
208 * Update IV
209 */
210 buf[3]++;
211 }
212
213 /*
214 * Do final encryption with reduced data
215 */
216 mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS );
217 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
218 p = output;
219
220 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
221 {
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;
225 }
226
227 mbedtls_aes_free( &aes_ctx );
228
229 return( 0 );
230}
231
232static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
233 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
234{
235 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
236 unsigned char *p = tmp;
237 int i, j;
238
239 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
240
241 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
242 {
243 /*
244 * Increase counter
245 */
246 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
247 if( ++ctx->counter[i - 1] != 0 )
248 break;
249
250 /*
251 * Crypt counter block
252 */
253 mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p );
254
255 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
256 }
257
258 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
259 tmp[i] ^= data[i];
260
261 /*
262 * Update key and counter
263 */
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 );
266
267 return( 0 );
268}
269
270void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
271 const unsigned char *additional, size_t add_len )
272{
273 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
274
275 if( add_len > 0 )
276 {
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;
281
282 block_cipher_df( add_input, additional, add_len );
283 ctr_drbg_update_internal( ctx, add_input );
284 }
285}
286
287int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
288 const unsigned char *additional, size_t len )
289{
290 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
291 size_t seedlen = 0;
292
293 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
294 len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
295 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
296
297 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
298
299 /*
300 * Gather entropy_len bytes of entropy to seed state
301 */
302 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
303 ctx->entropy_len ) )
304 {
305 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
306 }
307
308 seedlen += ctx->entropy_len;
309
310 /*
311 * Add additional data
312 */
313 if( additional && len )
314 {
315 memcpy( seed + seedlen, additional, len );
316 seedlen += len;
317 }
318
319 /*
320 * Reduce to 384 bits
321 */
322 block_cipher_df( seed, seed, seedlen );
323
324 /*
325 * Update state
326 */
327 ctr_drbg_update_internal( ctx, seed );
328 ctx->reseed_counter = 1;
329
330 return( 0 );
331}
332
333int mbedtls_ctr_drbg_random_with_add( void *p_rng,
334 unsigned char *output, size_t output_len,
335 const unsigned char *additional, size_t add_len )
336{
337 int ret = 0;
338 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
339 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
340 unsigned char *p = output;
341 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
342 int i;
343 size_t use_len;
344
345 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
346 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
347
348 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
349 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
350
351 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
352
353 if( ctx->reseed_counter > ctx->reseed_interval ||
354 ctx->prediction_resistance )
355 {
356 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
357 return( ret );
358
359 add_len = 0;
360 }
361
362 if( add_len > 0 )
363 {
364 block_cipher_df( add_input, additional, add_len );
365 ctr_drbg_update_internal( ctx, add_input );
366 }
367
368 while( output_len > 0 )
369 {
370 /*
371 * Increase counter
372 */
373 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
374 if( ++ctx->counter[i - 1] != 0 )
375 break;
376
377 /*
378 * Crypt counter block
379 */
380 mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp );
381
382 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
383 output_len;
384 /*
385 * Copy random block to destination
386 */
387 memcpy( p, tmp, use_len );
388 p += use_len;
389 output_len -= use_len;
390 }
391
392 ctr_drbg_update_internal( ctx, add_input );
393
394 ctx->reseed_counter++;
395
396 return( 0 );
397}
398
399int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
400{
401 int ret;
402 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
403
404#if defined(MBEDTLS_THREADING_C)
405 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
406 return( ret );
407#endif
408
409 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
410
411#if defined(MBEDTLS_THREADING_C)
412 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
413 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
414#endif
415
416 return( ret );
417}
418
419#if defined(MBEDTLS_FS_IO)
420int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
421{
422 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
423 FILE *f;
424 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
425
426 if( ( f = fopen( path, "wb" ) ) == NULL )
427 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
428
429 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
430 goto exit;
431
432 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
433 {
434 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
435 goto exit;
436 }
437
438 ret = 0;
439
440exit:
441 fclose( f );
442 return( ret );
443}
444
445int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
446{
447 FILE *f;
448 size_t n;
449 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
450
451 if( ( f = fopen( path, "rb" ) ) == NULL )
452 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
453
454 fseek( f, 0, SEEK_END );
455 n = (size_t) ftell( f );
456 fseek( f, 0, SEEK_SET );
457
458 if( n > MBEDTLS_CTR_DRBG_MAX_INPUT )
459 {
460 fclose( f );
461 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
462 }
463
464 if( fread( buf, 1, n, f ) != n )
465 {
466 fclose( f );
467 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
468 }
469
470 fclose( f );
471
472 mbedtls_ctr_drbg_update( ctx, buf, n );
473
474 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
475}
476#endif /* MBEDTLS_FS_IO */
477
478#if defined(MBEDTLS_SELF_TEST)
479
480static const unsigned char entropy_source_pr[96] =
481 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
482 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
483 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
484 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
485 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
486 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
487 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
488 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
489 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
490 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
491 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
492 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
493
494static const unsigned char entropy_source_nopr[64] =
495 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
496 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
497 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
498 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
499 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
500 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
501 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
502 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
503
504static const unsigned char nonce_pers_pr[16] =
505 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
506 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
507
508static const unsigned char nonce_pers_nopr[16] =
509 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
510 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
511
512static const unsigned char result_pr[16] =
513 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
514 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
515
516static const unsigned char result_nopr[16] =
517 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
518 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
519
520static size_t test_offset;
521static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
522 size_t len )
523{
524 const unsigned char *p = data;
525 memcpy( buf, p + test_offset, len );
526 test_offset += len;
527 return( 0 );
528}
529
530#define CHK( c ) if( (c) != 0 ) \
531 { \
532 if( verbose != 0 ) \
533 mbedtls_printf( "failed\n" ); \
534 return( 1 ); \
535 }
536
537/*
538 * Checkup routine
539 */
540int mbedtls_ctr_drbg_self_test( int verbose )
541{
542 mbedtls_ctr_drbg_context ctx;
543 unsigned char buf[16];
544
545 mbedtls_ctr_drbg_init( &ctx );
546
547 /*
548 * Based on a NIST CTR_DRBG test vector (PR = True)
549 */
550 if( verbose != 0 )
551 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
552
553 test_offset = 0;
554 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
555 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
556 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
557 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
558 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
559 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
560
561 mbedtls_ctr_drbg_free( &ctx );
562
563 if( verbose != 0 )
564 mbedtls_printf( "passed\n" );
565
566 /*
567 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
568 */
569 if( verbose != 0 )
570 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
571
572 mbedtls_ctr_drbg_init( &ctx );
573
574 test_offset = 0;
575 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
576 (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
577 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
578 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
579 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
580 CHK( memcmp( buf, result_nopr, 16 ) );
581
582 mbedtls_ctr_drbg_free( &ctx );
583
584 if( verbose != 0 )
585 mbedtls_printf( "passed\n" );
586
587 if( verbose != 0 )
588 mbedtls_printf( "\n" );
589
590 return( 0 );
591}
592#endif /* MBEDTLS_SELF_TEST */
593
594#endif /* MBEDTLS_CTR_DRBG_C */