1 /*
2 * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
3 *
4 * Copyright The Mbed TLS Contributors
5 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6 *
7 * This file is provided under the Apache License 2.0, or the
8 * GNU General Public License v2.0 or later.
9 *
10 * **********
11 * Apache License 2.0:
12 *
13 * Licensed under the Apache License, Version 2.0 (the "License"); you may
14 * not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 * http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
21 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
24 *
25 * **********
26 *
27 * **********
28 * GNU General Public License v2.0 or later:
29 *
30 * This program is free software; you can redistribute it and/or modify
31 * it under the terms of the GNU General Public License as published by
32 * the Free Software Foundation; either version 2 of the License, or
33 * (at your option) any later version.
34 *
35 * This program is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
39 *
40 * You should have received a copy of the GNU General Public License along
41 * with this program; if not, write to the Free Software Foundation, Inc.,
42 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
43 *
44 * **********
45 */
46 /*
47 * The NIST SP 800-90 DRBGs are described in the following publication.
48 *
49 * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
50 */
51
52 #if !defined(MBEDTLS_CONFIG_FILE)
53 #include "mbedtls/config.h"
54 #else
55 #include MBEDTLS_CONFIG_FILE
56 #endif
57
58 #if defined(MBEDTLS_CTR_DRBG_C)
59
60 #include "mbedtls/ctr_drbg.h"
61 #include "mbedtls/platform_util.h"
62
63 #include <string.h>
64
65 #if defined(MBEDTLS_FS_IO)
66 #include <stdio.h>
67 #endif
68
69 #if defined(MBEDTLS_SELF_TEST)
70 #if defined(MBEDTLS_PLATFORM_C)
71 #include "mbedtls/platform.h"
72 #else
73 #include <stdio.h>
74 #define mbedtls_printf printf
75 #endif /* MBEDTLS_PLATFORM_C */
76 #endif /* MBEDTLS_SELF_TEST */
77
78 /*
79 * CTR_DRBG context initialization
80 */
mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context * ctx)81 void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
82 {
83 memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
84
85 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
86 }
87
88 /*
89 * This function resets CTR_DRBG context to the state immediately
90 * after initial call of mbedtls_ctr_drbg_init().
91 */
mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context * ctx)92 void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
93 {
94 if( ctx == NULL )
95 return;
96
97 #if defined(MBEDTLS_THREADING_C)
98 /* The mutex is initialized iff f_entropy is set. */
99 if( ctx->f_entropy != NULL )
100 mbedtls_mutex_free( &ctx->mutex );
101 #endif
102 mbedtls_aes_free( &ctx->aes_ctx );
103 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
104 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
105 }
106
mbedtls_ctr_drbg_set_prediction_resistance(mbedtls_ctr_drbg_context * ctx,int resistance)107 void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
108 {
109 ctx->prediction_resistance = resistance;
110 }
111
mbedtls_ctr_drbg_set_entropy_len(mbedtls_ctr_drbg_context * ctx,size_t len)112 void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len )
113 {
114 ctx->entropy_len = len;
115 }
116
mbedtls_ctr_drbg_set_reseed_interval(mbedtls_ctr_drbg_context * ctx,int interval)117 void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval )
118 {
119 ctx->reseed_interval = interval;
120 }
121
block_cipher_df(unsigned char * output,const unsigned char * data,size_t data_len)122 static int block_cipher_df( unsigned char *output,
123 const unsigned char *data, size_t data_len )
124 {
125 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
126 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
127 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
128 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
129 unsigned char *p, *iv;
130 mbedtls_aes_context aes_ctx;
131 int ret = 0;
132
133 int i, j;
134 size_t buf_len, use_len;
135
136 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
137 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
138
139 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
140 mbedtls_aes_init( &aes_ctx );
141
142 /*
143 * Construct IV (16 bytes) and S in buffer
144 * IV = Counter (in 32-bits) padded to 16 with zeroes
145 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
146 * data || 0x80
147 * (Total is padded to a multiple of 16-bytes with zeroes)
148 */
149 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
150 *p++ = ( data_len >> 24 ) & 0xff;
151 *p++ = ( data_len >> 16 ) & 0xff;
152 *p++ = ( data_len >> 8 ) & 0xff;
153 *p++ = ( data_len ) & 0xff;
154 p += 3;
155 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
156 memcpy( p, data, data_len );
157 p[data_len] = 0x80;
158
159 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
160
161 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
162 key[i] = i;
163
164 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
165 {
166 goto exit;
167 }
168
169 /*
170 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
171 */
172 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
173 {
174 p = buf;
175 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
176 use_len = buf_len;
177
178 while( use_len > 0 )
179 {
180 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
181 chain[i] ^= p[i];
182 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
183 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
184 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
185
186 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ) ) != 0 )
187 {
188 goto exit;
189 }
190 }
191
192 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
193
194 /*
195 * Update IV
196 */
197 buf[3]++;
198 }
199
200 /*
201 * Do final encryption with reduced data
202 */
203 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
204 {
205 goto exit;
206 }
207 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
208 p = output;
209
210 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
211 {
212 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) ) != 0 )
213 {
214 goto exit;
215 }
216 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
217 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
218 }
219 exit:
220 mbedtls_aes_free( &aes_ctx );
221 /*
222 * tidy up the stack
223 */
224 mbedtls_platform_zeroize( buf, sizeof( buf ) );
225 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
226 mbedtls_platform_zeroize( key, sizeof( key ) );
227 mbedtls_platform_zeroize( chain, sizeof( chain ) );
228 if( 0 != ret )
229 {
230 /*
231 * wipe partial seed from memory
232 */
233 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
234 }
235
236 return( ret );
237 }
238
239 /* CTR_DRBG_Update (SP 800-90A §10.2.1.2)
240 * ctr_drbg_update_internal(ctx, provided_data)
241 * implements
242 * CTR_DRBG_Update(provided_data, Key, V)
243 * with inputs and outputs
244 * ctx->aes_ctx = Key
245 * ctx->counter = V
246 */
ctr_drbg_update_internal(mbedtls_ctr_drbg_context * ctx,const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN])247 static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
248 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
249 {
250 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
251 unsigned char *p = tmp;
252 int i, j;
253 int ret = 0;
254
255 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
256
257 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
258 {
259 /*
260 * Increase counter
261 */
262 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
263 if( ++ctx->counter[i - 1] != 0 )
264 break;
265
266 /*
267 * Crypt counter block
268 */
269 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 )
270 goto exit;
271
272 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
273 }
274
275 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
276 tmp[i] ^= data[i];
277
278 /*
279 * Update key and counter
280 */
281 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
282 goto exit;
283 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
284
285 exit:
286 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
287 return( ret );
288 }
289
290 /* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2)
291 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
292 * implements
293 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
294 * security_strength) -> initial_working_state
295 * with inputs
296 * ctx->counter = all-bits-0
297 * ctx->aes_ctx = context from all-bits-0 key
298 * additional[:add_len] = entropy_input || nonce || personalization_string
299 * and with outputs
300 * ctx = initial_working_state
301 */
mbedtls_ctr_drbg_update_ret(mbedtls_ctr_drbg_context * ctx,const unsigned char * additional,size_t add_len)302 int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
303 const unsigned char *additional,
304 size_t add_len )
305 {
306 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
307 int ret;
308
309 if( add_len == 0 )
310 return( 0 );
311
312 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
313 goto exit;
314 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
315 goto exit;
316
317 exit:
318 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
319 return( ret );
320 }
321
322 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context * ctx,const unsigned char * additional,size_t add_len)323 void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
324 const unsigned char *additional,
325 size_t add_len )
326 {
327 /* MAX_INPUT would be more logical here, but we have to match
328 * block_cipher_df()'s limits since we can't propagate errors */
329 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
330 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
331 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
332 }
333 #endif /* MBEDTLS_DEPRECATED_REMOVED */
334
335 /* CTR_DRBG_Reseed with derivation function (SP 800-90A §10.2.1.4.2)
336 * mbedtls_ctr_drbg_reseed(ctx, additional, len)
337 * implements
338 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
339 * -> new_working_state
340 * with inputs
341 * ctx contains working_state
342 * additional[:len] = additional_input
343 * and entropy_input comes from calling ctx->f_entropy
344 * and with output
345 * ctx contains new_working_state
346 */
mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context * ctx,const unsigned char * additional,size_t len)347 int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
348 const unsigned char *additional, size_t len )
349 {
350 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
351 size_t seedlen = 0;
352 int ret;
353
354 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
355 len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
356 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
357
358 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
359
360 /*
361 * Gather entropy_len bytes of entropy to seed state
362 */
363 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
364 ctx->entropy_len ) )
365 {
366 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
367 }
368
369 seedlen += ctx->entropy_len;
370
371 /*
372 * Add additional data
373 */
374 if( additional && len )
375 {
376 memcpy( seed + seedlen, additional, len );
377 seedlen += len;
378 }
379
380 /*
381 * Reduce to 384 bits
382 */
383 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
384 goto exit;
385
386 /*
387 * Update state
388 */
389 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
390 goto exit;
391 ctx->reseed_counter = 1;
392
393 exit:
394 mbedtls_platform_zeroize( seed, sizeof( seed ) );
395 return( ret );
396 }
397
398 /* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2)
399 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
400 * implements
401 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
402 * security_strength) -> initial_working_state
403 * with inputs
404 * custom[:len] = nonce || personalization_string
405 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
406 * and with outputs
407 * ctx = initial_working_state
408 */
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)409 int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
410 int (*f_entropy)(void *, unsigned char *, size_t),
411 void *p_entropy,
412 const unsigned char *custom,
413 size_t len )
414 {
415 int ret;
416 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
417
418 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
419
420 /* The mutex is initialized iff f_entropy is set. */
421 #if defined(MBEDTLS_THREADING_C)
422 mbedtls_mutex_init( &ctx->mutex );
423 #endif
424
425 mbedtls_aes_init( &ctx->aes_ctx );
426
427 ctx->f_entropy = f_entropy;
428 ctx->p_entropy = p_entropy;
429
430 if( ctx->entropy_len == 0 )
431 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
432
433 /*
434 * Initialize with an empty key
435 */
436 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
437 {
438 return( ret );
439 }
440
441 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
442 {
443 return( ret );
444 }
445 return( 0 );
446 }
447
448 /* Backward compatibility wrapper */
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)449 int mbedtls_ctr_drbg_seed_entropy_len(
450 mbedtls_ctr_drbg_context *ctx,
451 int (*f_entropy)(void *, unsigned char *, size_t), void *p_entropy,
452 const unsigned char *custom, size_t len,
453 size_t entropy_len )
454 {
455 mbedtls_ctr_drbg_set_entropy_len( ctx, entropy_len );
456 return( mbedtls_ctr_drbg_seed( ctx, f_entropy, p_entropy, custom, len ) );
457 }
458
459 /* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2)
460 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
461 * implements
462 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
463 * -> working_state_after_reseed
464 * if required, then
465 * CTR_DRBG_Generate(working_state_after_reseed,
466 * requested_number_of_bits, additional_input)
467 * -> status, returned_bits, new_working_state
468 * with inputs
469 * ctx contains working_state
470 * requested_number_of_bits = 8 * output_len
471 * additional[:add_len] = additional_input
472 * and entropy_input comes from calling ctx->f_entropy
473 * and with outputs
474 * status = SUCCESS (this function does the reseed internally)
475 * returned_bits = output[:output_len]
476 * ctx contains new_working_state
477 */
mbedtls_ctr_drbg_random_with_add(void * p_rng,unsigned char * output,size_t output_len,const unsigned char * additional,size_t add_len)478 int mbedtls_ctr_drbg_random_with_add( void *p_rng,
479 unsigned char *output, size_t output_len,
480 const unsigned char *additional, size_t add_len )
481 {
482 int ret = 0;
483 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
484 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
485 unsigned char *p = output;
486 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
487 int i;
488 size_t use_len;
489
490 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
491 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
492
493 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
494 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
495
496 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
497
498 if( ctx->reseed_counter > ctx->reseed_interval ||
499 ctx->prediction_resistance )
500 {
501 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
502 {
503 return( ret );
504 }
505 add_len = 0;
506 }
507
508 if( add_len > 0 )
509 {
510 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
511 goto exit;
512 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
513 goto exit;
514 }
515
516 while( output_len > 0 )
517 {
518 /*
519 * Increase counter
520 */
521 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
522 if( ++ctx->counter[i - 1] != 0 )
523 break;
524
525 /*
526 * Crypt counter block
527 */
528 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 )
529 goto exit;
530
531 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
532 output_len;
533 /*
534 * Copy random block to destination
535 */
536 memcpy( p, tmp, use_len );
537 p += use_len;
538 output_len -= use_len;
539 }
540
541 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
542 goto exit;
543
544 ctx->reseed_counter++;
545
546 exit:
547 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
548 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
549 return( ret );
550 }
551
mbedtls_ctr_drbg_random(void * p_rng,unsigned char * output,size_t output_len)552 int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
553 {
554 int ret;
555 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
556
557 #if defined(MBEDTLS_THREADING_C)
558 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
559 return( ret );
560 #endif
561
562 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
563
564 #if defined(MBEDTLS_THREADING_C)
565 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
566 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
567 #endif
568
569 return( ret );
570 }
571
572 #if defined(MBEDTLS_FS_IO)
mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context * ctx,const char * path)573 int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
574 {
575 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
576 FILE *f;
577 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
578
579 if( ( f = fopen( path, "wb" ) ) == NULL )
580 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
581
582 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
583 goto exit;
584
585 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
586 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
587 else
588 ret = 0;
589
590 exit:
591 mbedtls_platform_zeroize( buf, sizeof( buf ) );
592
593 fclose( f );
594 return( ret );
595 }
596
mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context * ctx,const char * path)597 int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
598 {
599 int ret = 0;
600 FILE *f = NULL;
601 size_t n;
602 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
603 unsigned char c;
604
605 if( ( f = fopen( path, "rb" ) ) == NULL )
606 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
607
608 n = fread( buf, 1, sizeof( buf ), f );
609 if( fread( &c, 1, 1, f ) != 0 )
610 {
611 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
612 goto exit;
613 }
614 if( n == 0 || ferror( f ) )
615 {
616 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
617 goto exit;
618 }
619 fclose( f );
620 f = NULL;
621
622 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
623
624 exit:
625 mbedtls_platform_zeroize( buf, sizeof( buf ) );
626 if( f != NULL )
627 fclose( f );
628 if( ret != 0 )
629 return( ret );
630 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
631 }
632 #endif /* MBEDTLS_FS_IO */
633
634 #if defined(MBEDTLS_SELF_TEST)
635
636 static const unsigned char entropy_source_pr[96] =
637 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
638 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
639 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
640 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
641 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
642 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
643 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
644 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
645 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
646 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
647 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
648 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
649
650 static const unsigned char entropy_source_nopr[64] =
651 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
652 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
653 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
654 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
655 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
656 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
657 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
658 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
659
660 static const unsigned char nonce_pers_pr[16] =
661 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
662 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
663
664 static const unsigned char nonce_pers_nopr[16] =
665 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
666 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
667
668 static const unsigned char result_pr[16] =
669 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
670 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
671
672 static const unsigned char result_nopr[16] =
673 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
674 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
675
676 static size_t test_offset;
ctr_drbg_self_test_entropy(void * data,unsigned char * buf,size_t len)677 static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
678 size_t len )
679 {
680 const unsigned char *p = data;
681 memcpy( buf, p + test_offset, len );
682 test_offset += len;
683 return( 0 );
684 }
685
686 #define CHK( c ) if( (c) != 0 ) \
687 { \
688 if( verbose != 0 ) \
689 mbedtls_printf( "failed\n" ); \
690 return( 1 ); \
691 }
692
693 /*
694 * Checkup routine
695 */
mbedtls_ctr_drbg_self_test(int verbose)696 int mbedtls_ctr_drbg_self_test( int verbose )
697 {
698 mbedtls_ctr_drbg_context ctx;
699 unsigned char buf[16];
700
701 mbedtls_ctr_drbg_init( &ctx );
702
703 /*
704 * Based on a NIST CTR_DRBG test vector (PR = True)
705 */
706 if( verbose != 0 )
707 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
708
709 test_offset = 0;
710 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
711 CHK( mbedtls_ctr_drbg_seed( &ctx,
712 ctr_drbg_self_test_entropy,
713 (void *) entropy_source_pr,
714 nonce_pers_pr, 16 ) );
715 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
716 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
717 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
718 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
719
720 mbedtls_ctr_drbg_free( &ctx );
721
722 if( verbose != 0 )
723 mbedtls_printf( "passed\n" );
724
725 /*
726 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
727 */
728 if( verbose != 0 )
729 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
730
731 mbedtls_ctr_drbg_init( &ctx );
732
733 test_offset = 0;
734 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
735 CHK( mbedtls_ctr_drbg_seed( &ctx,
736 ctr_drbg_self_test_entropy,
737 (void *) entropy_source_nopr,
738 nonce_pers_nopr, 16 ) );
739 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
740 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
741 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
742 CHK( memcmp( buf, result_nopr, 16 ) );
743
744 mbedtls_ctr_drbg_free( &ctx );
745
746 if( verbose != 0 )
747 mbedtls_printf( "passed\n" );
748
749 if( verbose != 0 )
750 mbedtls_printf( "\n" );
751
752 return( 0 );
753 }
754 #endif /* MBEDTLS_SELF_TEST */
755
756 #endif /* MBEDTLS_CTR_DRBG_C */
757