1 /*
2 * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
3 *
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 * SPDX-License-Identifier: Apache-2.0
6 *
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 */
mbedtls_zeroize(void * v,size_t n)53 static 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 */
mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context * ctx)60 void 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 */
mbedtls_ctr_drbg_seed_entropy_len(mbedtls_ctr_drbg_context * ctx,int (* f_entropy)(void *,unsigned char *,size_t),void * p_entropy,const unsigned char * custom,size_t len,size_t entropy_len)73 int 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
mbedtls_ctr_drbg_seed(mbedtls_ctr_drbg_context * ctx,int (* f_entropy)(void *,unsigned char *,size_t),void * p_entropy,const unsigned char * custom,size_t len)105 int 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
mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context * ctx)115 void 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
mbedtls_ctr_drbg_set_prediction_resistance(mbedtls_ctr_drbg_context * ctx,int resistance)127 void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
128 {
129 ctx->prediction_resistance = resistance;
130 }
131
mbedtls_ctr_drbg_set_entropy_len(mbedtls_ctr_drbg_context * ctx,size_t len)132 void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len )
133 {
134 ctx->entropy_len = len;
135 }
136
mbedtls_ctr_drbg_set_reseed_interval(mbedtls_ctr_drbg_context * ctx,int interval)137 void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval )
138 {
139 ctx->reseed_interval = interval;
140 }
141
block_cipher_df(unsigned char * output,const unsigned char * data,size_t data_len)142 static 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
ctr_drbg_update_internal(mbedtls_ctr_drbg_context * ctx,const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN])232 static 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
mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context * ctx,const unsigned char * additional,size_t add_len)270 void 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
mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context * ctx,const unsigned char * additional,size_t len)287 int 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 + len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
294 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
295
296 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
297
298 /*
299 * Gather entropy_len bytes of entropy to seed state
300 */
301 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
302 ctx->entropy_len ) )
303 {
304 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
305 }
306
307 seedlen += ctx->entropy_len;
308
309 /*
310 * Add additional data
311 */
312 if( additional && len )
313 {
314 memcpy( seed + seedlen, additional, len );
315 seedlen += len;
316 }
317
318 /*
319 * Reduce to 384 bits
320 */
321 block_cipher_df( seed, seed, seedlen );
322
323 /*
324 * Update state
325 */
326 ctr_drbg_update_internal( ctx, seed );
327 ctx->reseed_counter = 1;
328
329 return( 0 );
330 }
331
mbedtls_ctr_drbg_random_with_add(void * p_rng,unsigned char * output,size_t output_len,const unsigned char * additional,size_t add_len)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 )
335 {
336 int ret = 0;
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];
341 int i;
342 size_t use_len;
343
344 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
345 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
346
347 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
348 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
349
350 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
351
352 if( ctx->reseed_counter > ctx->reseed_interval ||
353 ctx->prediction_resistance )
354 {
355 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
356 return( ret );
357
358 add_len = 0;
359 }
360
361 if( add_len > 0 )
362 {
363 block_cipher_df( add_input, additional, add_len );
364 ctr_drbg_update_internal( ctx, add_input );
365 }
366
367 while( output_len > 0 )
368 {
369 /*
370 * Increase counter
371 */
372 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
373 if( ++ctx->counter[i - 1] != 0 )
374 break;
375
376 /*
377 * Crypt counter block
378 */
379 mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp );
380
381 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
382 output_len;
383 /*
384 * Copy random block to destination
385 */
386 memcpy( p, tmp, use_len );
387 p += use_len;
388 output_len -= use_len;
389 }
390
391 ctr_drbg_update_internal( ctx, add_input );
392
393 ctx->reseed_counter++;
394
395 return( 0 );
396 }
397
mbedtls_ctr_drbg_random(void * p_rng,unsigned char * output,size_t output_len)398 int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
399 {
400 int ret;
401 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
402
403 #if defined(MBEDTLS_THREADING_C)
404 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
405 return( ret );
406 #endif
407
408 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
409
410 #if defined(MBEDTLS_THREADING_C)
411 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
412 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
413 #endif
414
415 return( ret );
416 }
417
418 #if defined(MBEDTLS_FS_IO)
mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context * ctx,const char * path)419 int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
420 {
421 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
422 FILE *f;
423 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
424
425 if( ( f = fopen( path, "wb" ) ) == NULL )
426 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
427
428 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
429 goto exit;
430
431 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
432 {
433 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
434 goto exit;
435 }
436
437 ret = 0;
438
439 exit:
440 fclose( f );
441 return( ret );
442 }
443
mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context * ctx,const char * path)444 int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
445 {
446 FILE *f;
447 size_t n;
448 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
449
450 if( ( f = fopen( path, "rb" ) ) == NULL )
451 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
452
453 fseek( f, 0, SEEK_END );
454 n = (size_t) ftell( f );
455 fseek( f, 0, SEEK_SET );
456
457 if( n > MBEDTLS_CTR_DRBG_MAX_INPUT )
458 {
459 fclose( f );
460 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
461 }
462
463 if( fread( buf, 1, n, f ) != n )
464 {
465 fclose( f );
466 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
467 }
468
469 fclose( f );
470
471 mbedtls_ctr_drbg_update( ctx, buf, n );
472
473 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
474 }
475 #endif /* MBEDTLS_FS_IO */
476
477 #if defined(MBEDTLS_SELF_TEST)
478
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 };
492
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 };
502
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 };
506
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 };
510
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 };
514
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 };
518
519 static size_t test_offset;
ctr_drbg_self_test_entropy(void * data,unsigned char * buf,size_t len)520 static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
521 size_t len )
522 {
523 const unsigned char *p = data;
524 memcpy( buf, p + test_offset, len );
525 test_offset += len;
526 return( 0 );
527 }
528
529 #define CHK( c ) if( (c) != 0 ) \
530 { \
531 if( verbose != 0 ) \
532 mbedtls_printf( "failed\n" ); \
533 return( 1 ); \
534 }
535
536 /*
537 * Checkup routine
538 */
mbedtls_ctr_drbg_self_test(int verbose)539 int mbedtls_ctr_drbg_self_test( int verbose )
540 {
541 mbedtls_ctr_drbg_context ctx;
542 unsigned char buf[16];
543
544 mbedtls_ctr_drbg_init( &ctx );
545
546 /*
547 * Based on a NIST CTR_DRBG test vector (PR = True)
548 */
549 if( verbose != 0 )
550 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
551
552 test_offset = 0;
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 ) );
559
560 mbedtls_ctr_drbg_free( &ctx );
561
562 if( verbose != 0 )
563 mbedtls_printf( "passed\n" );
564
565 /*
566 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
567 */
568 if( verbose != 0 )
569 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
570
571 mbedtls_ctr_drbg_init( &ctx );
572
573 test_offset = 0;
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 ) );
580
581 mbedtls_ctr_drbg_free( &ctx );
582
583 if( verbose != 0 )
584 mbedtls_printf( "passed\n" );
585
586 if( verbose != 0 )
587 mbedtls_printf( "\n" );
588
589 return( 0 );
590 }
591 #endif /* MBEDTLS_SELF_TEST */
592
593 #endif /* MBEDTLS_CTR_DRBG_C */
594