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