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