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