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
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 /*
20  *  The NIST SP 800-90 DRBGs are described in the following publication.
21  *
22  *  http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
23  */
24 
25 #include "common.h"
26 
27 #if defined(MBEDTLS_CTR_DRBG_C)
28 
29 #include "mbedtls/ctr_drbg.h"
30 #include "mbedtls/platform_util.h"
31 #include "mbedtls/error.h"
32 
33 #include <string.h>
34 
35 #if defined(MBEDTLS_FS_IO)
36 #include <stdio.h>
37 #endif
38 
39 #if defined(MBEDTLS_SELF_TEST)
40 #if defined(MBEDTLS_PLATFORM_C)
41 #include "mbedtls/platform.h"
42 #else
43 #include <stdio.h>
44 #define vdb_mbedtls_printf printf
45 #endif /* MBEDTLS_PLATFORM_C */
46 #endif /* MBEDTLS_SELF_TEST */
47 
48 /*
49  * CTR_DRBG context initialization
50  */
vdb_mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context * ctx)51 void vdb_mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
52 {
53     memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
54     /* Indicate that the entropy nonce length is not set explicitly.
55      * See mbedtls_ctr_drbg_set_nonce_len(). */
56     ctx->reseed_counter = -1;
57 
58     ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
59 
60 #if defined(MBEDTLS_THREADING_C)
61     mbedtls_mutex_init( &ctx->mutex );
62 #endif
63 }
64 
65 /*
66  *  This function resets CTR_DRBG context to the state immediately
67  *  after initial call of vdb_mbedtls_ctr_drbg_init().
68  */
vdb_mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context * ctx)69 void vdb_mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
70 {
71     if( ctx == NULL )
72         return;
73 
74 #if defined(MBEDTLS_THREADING_C)
75     mbedtls_mutex_free( &ctx->mutex );
76 #endif
77     vdb_mbedtls_aes_free( &ctx->aes_ctx );
78     vdb_mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
79     ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
80     ctx->reseed_counter = -1;
81 #if defined(MBEDTLS_THREADING_C)
82     mbedtls_mutex_init( &ctx->mutex );
83 #endif
84 }
85 
vdb_mbedtls_ctr_drbg_set_prediction_resistance(mbedtls_ctr_drbg_context * ctx,int resistance)86 void vdb_mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx,
87                                                  int resistance )
88 {
89     ctx->prediction_resistance = resistance;
90 }
91 
vdb_mbedtls_ctr_drbg_set_entropy_len(mbedtls_ctr_drbg_context * ctx,size_t len)92 void vdb_mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx,
93                                        size_t len )
94 {
95     ctx->entropy_len = len;
96 }
97 
mbedtls_ctr_drbg_set_nonce_len(mbedtls_ctr_drbg_context * ctx,size_t len)98 int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx,
99                                     size_t len )
100 {
101     /* If vdb_mbedtls_ctr_drbg_seed() has already been called, it's
102      * too late. Return the error code that's closest to making sense. */
103     if( ctx->f_entropy != NULL )
104         return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
105 
106     if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
107         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
108 #if SIZE_MAX > INT_MAX
109     /* This shouldn't be an issue because
110      * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible
111      * configuration, but make sure anyway. */
112     if( len > INT_MAX )
113         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
114 #endif
115 
116     /* For backward compatibility with Mbed TLS <= 2.19, store the
117      * entropy nonce length in a field that already exists, but isn't
118      * used until after the initial seeding. */
119     /* Due to the capping of len above, the value fits in an int. */
120     ctx->reseed_counter = (int) len;
121     return( 0 );
122 }
123 
vdb_mbedtls_ctr_drbg_set_reseed_interval(mbedtls_ctr_drbg_context * ctx,int interval)124 void vdb_mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx,
125                                            int interval )
126 {
127     ctx->reseed_interval = interval;
128 }
129 
block_cipher_df(unsigned char * output,const unsigned char * data,size_t data_len)130 static int block_cipher_df( unsigned char *output,
131                             const unsigned char *data, size_t data_len )
132 {
133     unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
134                       MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
135     unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
136     unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
137     unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
138     unsigned char *p, *iv;
139     mbedtls_aes_context aes_ctx;
140     int ret = 0;
141 
142     int i, j;
143     size_t buf_len, use_len;
144 
145     if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
146         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
147 
148     memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
149             MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
150     vdb_mbedtls_aes_init( &aes_ctx );
151 
152     /*
153      * Construct IV (16 bytes) and S in buffer
154      * IV = Counter (in 32-bits) padded to 16 with zeroes
155      * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
156      *     data || 0x80
157      *     (Total is padded to a multiple of 16-bytes with zeroes)
158      */
159     p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
160     *p++ = ( data_len >> 24 ) & 0xff;
161     *p++ = ( data_len >> 16 ) & 0xff;
162     *p++ = ( data_len >> 8  ) & 0xff;
163     *p++ = ( data_len       ) & 0xff;
164     p += 3;
165     *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
166     memcpy( p, data, data_len );
167     p[data_len] = 0x80;
168 
169     buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
170 
171     for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
172         key[i] = i;
173 
174     if( ( ret = vdb_mbedtls_aes_setkey_enc( &aes_ctx, key,
175                                         MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
176     {
177         goto exit;
178     }
179 
180     /*
181      * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
182      */
183     for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
184     {
185         p = buf;
186         memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
187         use_len = buf_len;
188 
189         while( use_len > 0 )
190         {
191             for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
192                 chain[i] ^= p[i];
193             p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
194             use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
195                        MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
196 
197             if( ( ret = vdb_mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
198                                                chain, chain ) ) != 0 )
199             {
200                 goto exit;
201             }
202         }
203 
204         memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
205 
206         /*
207          * Update IV
208          */
209         buf[3]++;
210     }
211 
212     /*
213      * Do final encryption with reduced data
214      */
215     if( ( ret = vdb_mbedtls_aes_setkey_enc( &aes_ctx, tmp,
216                                         MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
217     {
218         goto exit;
219     }
220     iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
221     p = output;
222 
223     for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
224     {
225         if( ( ret = vdb_mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
226                                            iv, iv ) ) != 0 )
227         {
228             goto exit;
229         }
230         memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
231         p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
232     }
233 exit:
234     vdb_mbedtls_aes_free( &aes_ctx );
235     /*
236     * tidy up the stack
237     */
238     vdb_mbedtls_platform_zeroize( buf, sizeof( buf ) );
239     vdb_mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
240     vdb_mbedtls_platform_zeroize( key, sizeof( key ) );
241     vdb_mbedtls_platform_zeroize( chain, sizeof( chain ) );
242     if( 0 != ret )
243     {
244         /*
245         * wipe partial seed from memory
246         */
247         vdb_mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
248     }
249 
250     return( ret );
251 }
252 
253 /* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
254  * ctr_drbg_update_internal(ctx, provided_data)
255  * implements
256  * CTR_DRBG_Update(provided_data, Key, V)
257  * with inputs and outputs
258  *   ctx->aes_ctx = Key
259  *   ctx->counter = V
260  */
ctr_drbg_update_internal(mbedtls_ctr_drbg_context * ctx,const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN])261 static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
262                           const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
263 {
264     unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
265     unsigned char *p = tmp;
266     int i, j;
267     int ret = 0;
268 
269     memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
270 
271     for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
272     {
273         /*
274          * Increase counter
275          */
276         for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
277             if( ++ctx->counter[i - 1] != 0 )
278                 break;
279 
280         /*
281          * Crypt counter block
282          */
283         if( ( ret = vdb_mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
284                                            ctx->counter, p ) ) != 0 )
285         {
286             goto exit;
287         }
288 
289         p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
290     }
291 
292     for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
293         tmp[i] ^= data[i];
294 
295     /*
296      * Update key and counter
297      */
298     if( ( ret = vdb_mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp,
299                                         MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
300     {
301         goto exit;
302     }
303     memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
304             MBEDTLS_CTR_DRBG_BLOCKSIZE );
305 
306 exit:
307     vdb_mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
308     return( ret );
309 }
310 
311 /* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
312  * vdb_mbedtls_ctr_drbg_update(ctx, additional, add_len)
313  * implements
314  * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
315  *                      security_strength) -> initial_working_state
316  * with inputs
317  *   ctx->counter = all-bits-0
318  *   ctx->aes_ctx = context from all-bits-0 key
319  *   additional[:add_len] = entropy_input || nonce || personalization_string
320  * and with outputs
321  *   ctx = initial_working_state
322  */
vdb_mbedtls_ctr_drbg_update_ret(mbedtls_ctr_drbg_context * ctx,const unsigned char * additional,size_t add_len)323 int vdb_mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
324                                  const unsigned char *additional,
325                                  size_t add_len )
326 {
327     unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
328     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
329 
330     if( add_len == 0 )
331         return( 0 );
332 
333     if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
334         goto exit;
335     if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
336         goto exit;
337 
338 exit:
339     vdb_mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
340     return( ret );
341 }
342 
343 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
vdb_mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context * ctx,const unsigned char * additional,size_t add_len)344 void vdb_mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
345                               const unsigned char *additional,
346                               size_t add_len )
347 {
348     /* MAX_INPUT would be more logical here, but we have to match
349      * block_cipher_df()'s limits since we can't propagate errors */
350     if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
351         add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
352     (void) vdb_mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
353 }
354 #endif /* MBEDTLS_DEPRECATED_REMOVED */
355 
356 /* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
357  * vdb_mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
358  * implements
359  * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
360  *                -> new_working_state
361  * with inputs
362  *   ctx contains working_state
363  *   additional[:len] = additional_input
364  * and entropy_input comes from calling ctx->f_entropy
365  *                              for (ctx->entropy_len + nonce_len) bytes
366  * and with output
367  *   ctx contains new_working_state
368  */
mbedtls_ctr_drbg_reseed_internal(mbedtls_ctr_drbg_context * ctx,const unsigned char * additional,size_t len,size_t nonce_len)369 static int mbedtls_ctr_drbg_reseed_internal( mbedtls_ctr_drbg_context *ctx,
370                                              const unsigned char *additional,
371                                              size_t len,
372                                              size_t nonce_len )
373 {
374     unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
375     size_t seedlen = 0;
376     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
377 
378     if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
379         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
380     if( nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
381         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
382     if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len )
383         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
384 
385     memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
386 
387     /* Gather entropy_len bytes of entropy to seed state. */
388     if( 0 != ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) )
389     {
390         return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
391     }
392     seedlen += ctx->entropy_len;
393 
394     /* Gather entropy for a nonce if requested. */
395     if( nonce_len != 0 )
396     {
397         if( 0 != ctx->f_entropy( ctx->p_entropy, seed, nonce_len ) )
398         {
399             return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
400         }
401         seedlen += nonce_len;
402     }
403 
404     /* Add additional data if provided. */
405     if( additional != NULL && len != 0 )
406     {
407         memcpy( seed + seedlen, additional, len );
408         seedlen += len;
409     }
410 
411     /* Reduce to 384 bits. */
412     if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
413         goto exit;
414 
415     /* Update state. */
416     if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
417         goto exit;
418     ctx->reseed_counter = 1;
419 
420 exit:
421     vdb_mbedtls_platform_zeroize( seed, sizeof( seed ) );
422     return( ret );
423 }
424 
vdb_mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context * ctx,const unsigned char * additional,size_t len)425 int vdb_mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
426                              const unsigned char *additional, size_t len )
427 {
428     return( mbedtls_ctr_drbg_reseed_internal( ctx, additional, len, 0 ) );
429 }
430 
431 /* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
432  * is sufficient to achieve the maximum security strength given the key
433  * size and entropy length. If there is enough entropy in the initial
434  * call to the entropy function to serve as both the entropy input and
435  * the nonce, don't make a second call to get a nonce. */
good_nonce_len(size_t entropy_len)436 static size_t good_nonce_len( size_t entropy_len )
437 {
438     if( entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 )
439         return( 0 );
440     else
441         return( ( entropy_len + 1 ) / 2 );
442 }
443 
444 /* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
445  * vdb_mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
446  * implements
447  * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
448  *                      security_strength) -> initial_working_state
449  * with inputs
450  *   custom[:len] = nonce || personalization_string
451  * where entropy_input comes from f_entropy for ctx->entropy_len bytes
452  * and with outputs
453  *   ctx = initial_working_state
454  */
vdb_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)455 int vdb_mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
456                            int (*f_entropy)(void *, unsigned char *, size_t),
457                            void *p_entropy,
458                            const unsigned char *custom,
459                            size_t len )
460 {
461     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
462     unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
463     size_t nonce_len;
464 
465     memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
466 
467     vdb_mbedtls_aes_init( &ctx->aes_ctx );
468 
469     ctx->f_entropy = f_entropy;
470     ctx->p_entropy = p_entropy;
471 
472     if( ctx->entropy_len == 0 )
473         ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
474     /* ctx->reseed_counter contains the desired amount of entropy to
475      * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
476      * If it's -1, indicating that the entropy nonce length was not set
477      * explicitly, use a sufficiently large nonce for security. */
478     nonce_len = ( ctx->reseed_counter >= 0 ?
479                   (size_t) ctx->reseed_counter :
480                   good_nonce_len( ctx->entropy_len ) );
481 
482     /* Initialize with an empty key. */
483     if( ( ret = vdb_mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
484                                         MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
485     {
486         return( ret );
487     }
488 
489     /* Do the initial seeding. */
490     if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len,
491                                                   nonce_len ) ) != 0 )
492     {
493         return( ret );
494     }
495     return( 0 );
496 }
497 
498 /* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
499  * vdb_mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
500  * implements
501  * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
502  *                -> working_state_after_reseed
503  *                if required, then
504  * CTR_DRBG_Generate(working_state_after_reseed,
505  *                   requested_number_of_bits, additional_input)
506  *                -> status, returned_bits, new_working_state
507  * with inputs
508  *   ctx contains working_state
509  *   requested_number_of_bits = 8 * output_len
510  *   additional[:add_len] = additional_input
511  * and entropy_input comes from calling ctx->f_entropy
512  * and with outputs
513  *   status = SUCCESS (this function does the reseed internally)
514  *   returned_bits = output[:output_len]
515  *   ctx contains new_working_state
516  */
vdb_mbedtls_ctr_drbg_random_with_add(void * p_rng,unsigned char * output,size_t output_len,const unsigned char * additional,size_t add_len)517 int vdb_mbedtls_ctr_drbg_random_with_add( void *p_rng,
518                               unsigned char *output, size_t output_len,
519                               const unsigned char *additional, size_t add_len )
520 {
521     int ret = 0;
522     mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
523     unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
524     unsigned char *p = output;
525     unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
526     int i;
527     size_t use_len;
528 
529     if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
530         return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
531 
532     if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
533         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
534 
535     memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
536 
537     if( ctx->reseed_counter > ctx->reseed_interval ||
538         ctx->prediction_resistance )
539     {
540         if( ( ret = vdb_mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
541         {
542             return( ret );
543         }
544         add_len = 0;
545     }
546 
547     if( add_len > 0 )
548     {
549         if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
550             goto exit;
551         if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
552             goto exit;
553     }
554 
555     while( output_len > 0 )
556     {
557         /*
558          * Increase counter
559          */
560         for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
561             if( ++ctx->counter[i - 1] != 0 )
562                 break;
563 
564         /*
565          * Crypt counter block
566          */
567         if( ( ret = vdb_mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
568                                            ctx->counter, tmp ) ) != 0 )
569         {
570             goto exit;
571         }
572 
573         use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE )
574             ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
575         /*
576          * Copy random block to destination
577          */
578         memcpy( p, tmp, use_len );
579         p += use_len;
580         output_len -= use_len;
581     }
582 
583     if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
584         goto exit;
585 
586     ctx->reseed_counter++;
587 
588 exit:
589     vdb_mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
590     vdb_mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
591     return( ret );
592 }
593 
vdb_mbedtls_ctr_drbg_random(void * p_rng,unsigned char * output,size_t output_len)594 int vdb_mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output,
595                              size_t output_len )
596 {
597     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
598     mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
599 
600 #if defined(MBEDTLS_THREADING_C)
601     if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
602         return( ret );
603 #endif
604 
605     ret = vdb_mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
606 
607 #if defined(MBEDTLS_THREADING_C)
608     if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
609         return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
610 #endif
611 
612     return( ret );
613 }
614 
615 #if defined(MBEDTLS_FS_IO)
vdb_mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context * ctx,const char * path)616 int vdb_mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx,
617                                       const char *path )
618 {
619     int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
620     FILE *f;
621     unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
622 
623     if( ( f = fopen( path, "wb" ) ) == NULL )
624         return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
625 
626     if( ( ret = vdb_mbedtls_ctr_drbg_random( ctx, buf,
627                                          MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
628         goto exit;
629 
630     if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) !=
631         MBEDTLS_CTR_DRBG_MAX_INPUT )
632     {
633         ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
634     }
635     else
636     {
637         ret = 0;
638     }
639 
640 exit:
641     vdb_mbedtls_platform_zeroize( buf, sizeof( buf ) );
642 
643     fclose( f );
644     return( ret );
645 }
646 
vdb_mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context * ctx,const char * path)647 int vdb_mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx,
648                                        const char *path )
649 {
650     int ret = 0;
651     FILE *f = NULL;
652     size_t n;
653     unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
654     unsigned char c;
655 
656     if( ( f = fopen( path, "rb" ) ) == NULL )
657         return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
658 
659     n = fread( buf, 1, sizeof( buf ), f );
660     if( fread( &c, 1, 1, f ) != 0 )
661     {
662         ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
663         goto exit;
664     }
665     if( n == 0 || ferror( f ) )
666     {
667         ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
668         goto exit;
669     }
670     fclose( f );
671     f = NULL;
672 
673     ret = vdb_mbedtls_ctr_drbg_update_ret( ctx, buf, n );
674 
675 exit:
676     vdb_mbedtls_platform_zeroize( buf, sizeof( buf ) );
677     if( f != NULL )
678         fclose( f );
679     if( ret != 0 )
680         return( ret );
681     return( vdb_mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
682 }
683 #endif /* MBEDTLS_FS_IO */
684 
685 #if defined(MBEDTLS_SELF_TEST)
686 
687 static const unsigned char entropy_source_pr[96] =
688     { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
689       0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
690       0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
691       0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
692       0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
693       0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
694       0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
695       0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
696       0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
697       0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
698       0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
699       0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
700 
701 static const unsigned char entropy_source_nopr[64] =
702     { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
703       0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
704       0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
705       0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
706       0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
707       0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
708       0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
709       0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
710 
711 static const unsigned char nonce_pers_pr[16] =
712     { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
713       0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
714 
715 static const unsigned char nonce_pers_nopr[16] =
716     { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
717       0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
718 
719 #if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
720 static const unsigned char result_pr[16] =
721     { 0x95, 0x3c, 0xa5, 0xbd, 0x44, 0x1, 0x34, 0xb7,
722       0x13, 0x58, 0x3e, 0x6a, 0x6c, 0x7e, 0x88, 0x8a };
723 
724 static const unsigned char result_nopr[16] =
725     { 0x6c, 0x25, 0x27, 0x95, 0xa3, 0x62, 0xd6, 0xdb,
726       0x90, 0xfd, 0x69, 0xb5, 0x42, 0x9, 0x4b, 0x84 };
727 #else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
728 static const unsigned char result_pr[16] =
729     { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
730       0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
731 
732 static const unsigned char result_nopr[16] =
733     { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
734       0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
735 #endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
736 
737 static size_t test_offset;
ctr_drbg_self_test_entropy(void * data,unsigned char * buf,size_t len)738 static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
739                                        size_t len )
740 {
741     const unsigned char *p = data;
742     memcpy( buf, p + test_offset, len );
743     test_offset += len;
744     return( 0 );
745 }
746 
747 #define CHK( c )    if( (c) != 0 )                          \
748                     {                                       \
749                         if( verbose != 0 )                  \
750                             vdb_mbedtls_printf( "failed\n" );  \
751                         return( 1 );                        \
752                     }
753 
754 /*
755  * Checkup routine
756  */
vdb_mbedtls_ctr_drbg_self_test(int verbose)757 int vdb_mbedtls_ctr_drbg_self_test( int verbose )
758 {
759     mbedtls_ctr_drbg_context ctx;
760     unsigned char buf[16];
761 
762     vdb_mbedtls_ctr_drbg_init( &ctx );
763 
764     /*
765      * Based on a NIST CTR_DRBG test vector (PR = True)
766      */
767     if( verbose != 0 )
768         vdb_mbedtls_printf( "  CTR_DRBG (PR = TRUE) : " );
769 
770     test_offset = 0;
771     vdb_mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
772     mbedtls_ctr_drbg_set_nonce_len( &ctx, 0 );
773     CHK( vdb_mbedtls_ctr_drbg_seed( &ctx,
774                                 ctr_drbg_self_test_entropy,
775                                 (void *) entropy_source_pr,
776                                 nonce_pers_pr, 16 ) );
777     vdb_mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
778     CHK( vdb_mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
779     CHK( vdb_mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
780     CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
781 
782     vdb_mbedtls_ctr_drbg_free( &ctx );
783 
784     if( verbose != 0 )
785         vdb_mbedtls_printf( "passed\n" );
786 
787     /*
788      * Based on a NIST CTR_DRBG test vector (PR = FALSE)
789      */
790     if( verbose != 0 )
791         vdb_mbedtls_printf( "  CTR_DRBG (PR = FALSE): " );
792 
793     vdb_mbedtls_ctr_drbg_init( &ctx );
794 
795     test_offset = 0;
796     vdb_mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
797     mbedtls_ctr_drbg_set_nonce_len( &ctx, 0 );
798     CHK( vdb_mbedtls_ctr_drbg_seed( &ctx,
799                                 ctr_drbg_self_test_entropy,
800                                 (void *) entropy_source_nopr,
801                                 nonce_pers_nopr, 16 ) );
802     CHK( vdb_mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
803     CHK( vdb_mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
804     CHK( vdb_mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
805     CHK( memcmp( buf, result_nopr, 16 ) );
806 
807     vdb_mbedtls_ctr_drbg_free( &ctx );
808 
809     if( verbose != 0 )
810         vdb_mbedtls_printf( "passed\n" );
811 
812     if( verbose != 0 )
813             vdb_mbedtls_printf( "\n" );
814 
815     return( 0 );
816 }
817 #endif /* MBEDTLS_SELF_TEST */
818 
819 #endif /* MBEDTLS_CTR_DRBG_C */
820