xref: /reactos/dll/3rdparty/mbedtls/ctr_drbg.c (revision cbda039f)
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 &sect;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 &sect;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 &sect;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 &sect;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 &sect;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