xref: /optee_os/lib/libmbedtls/mbedtls/library/ctr_drbg.c (revision 7901324d9530594155991c8b283023d567741cc7)
1817466cbSJens Wiklander /*
2817466cbSJens Wiklander  *  CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
3817466cbSJens Wiklander  *
4*7901324dSJerome Forissier  *  Copyright The Mbed TLS Contributors
5*7901324dSJerome Forissier  *  SPDX-License-Identifier: Apache-2.0
6817466cbSJens Wiklander  *
7817466cbSJens Wiklander  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
8817466cbSJens Wiklander  *  not use this file except in compliance with the License.
9817466cbSJens Wiklander  *  You may obtain a copy of the License at
10817466cbSJens Wiklander  *
11817466cbSJens Wiklander  *  http://www.apache.org/licenses/LICENSE-2.0
12817466cbSJens Wiklander  *
13817466cbSJens Wiklander  *  Unless required by applicable law or agreed to in writing, software
14817466cbSJens Wiklander  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15817466cbSJens Wiklander  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16817466cbSJens Wiklander  *  See the License for the specific language governing permissions and
17817466cbSJens Wiklander  *  limitations under the License.
18817466cbSJens Wiklander  */
19817466cbSJens Wiklander /*
203d3b0591SJens Wiklander  *  The NIST SP 800-90 DRBGs are described in the following publication.
21817466cbSJens Wiklander  *
22817466cbSJens Wiklander  *  http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
23817466cbSJens Wiklander  */
24817466cbSJens Wiklander 
25*7901324dSJerome Forissier #include "common.h"
26817466cbSJens Wiklander 
27817466cbSJens Wiklander #if defined(MBEDTLS_CTR_DRBG_C)
28817466cbSJens Wiklander 
29817466cbSJens Wiklander #include "mbedtls/ctr_drbg.h"
303d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
3111fa71b9SJerome Forissier #include "mbedtls/error.h"
32817466cbSJens Wiklander 
33817466cbSJens Wiklander #include <string.h>
34817466cbSJens Wiklander 
35817466cbSJens Wiklander #if defined(MBEDTLS_FS_IO)
36817466cbSJens Wiklander #include <stdio.h>
37817466cbSJens Wiklander #endif
38817466cbSJens Wiklander 
39817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST)
40817466cbSJens Wiklander #if defined(MBEDTLS_PLATFORM_C)
41817466cbSJens Wiklander #include "mbedtls/platform.h"
42817466cbSJens Wiklander #else
43817466cbSJens Wiklander #include <stdio.h>
44817466cbSJens Wiklander #define mbedtls_printf printf
45817466cbSJens Wiklander #endif /* MBEDTLS_PLATFORM_C */
46817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST */
47817466cbSJens Wiklander 
48817466cbSJens Wiklander /*
49817466cbSJens Wiklander  * CTR_DRBG context initialization
50817466cbSJens Wiklander  */
51817466cbSJens Wiklander void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
52817466cbSJens Wiklander {
53817466cbSJens Wiklander     memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
5411fa71b9SJerome Forissier     /* Indicate that the entropy nonce length is not set explicitly.
5511fa71b9SJerome Forissier      * See mbedtls_ctr_drbg_set_nonce_len(). */
5611fa71b9SJerome Forissier     ctx->reseed_counter = -1;
57817466cbSJens Wiklander 
58*7901324dSJerome Forissier     ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
59817466cbSJens Wiklander }
60817466cbSJens Wiklander 
61*7901324dSJerome Forissier /*
62*7901324dSJerome Forissier  *  This function resets CTR_DRBG context to the state immediately
63*7901324dSJerome Forissier  *  after initial call of mbedtls_ctr_drbg_init().
64*7901324dSJerome Forissier  */
65817466cbSJens Wiklander void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
66817466cbSJens Wiklander {
67817466cbSJens Wiklander     if( ctx == NULL )
68817466cbSJens Wiklander         return;
69817466cbSJens Wiklander 
70817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C)
71*7901324dSJerome Forissier     /* The mutex is initialized iff f_entropy is set. */
72*7901324dSJerome Forissier     if( ctx->f_entropy != NULL )
73817466cbSJens Wiklander         mbedtls_mutex_free( &ctx->mutex );
74817466cbSJens Wiklander #endif
75817466cbSJens Wiklander     mbedtls_aes_free( &ctx->aes_ctx );
763d3b0591SJens Wiklander     mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
77*7901324dSJerome Forissier     ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
78*7901324dSJerome Forissier     ctx->reseed_counter = -1;
79817466cbSJens Wiklander }
80817466cbSJens Wiklander 
8111fa71b9SJerome Forissier void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx,
8211fa71b9SJerome Forissier                                                  int resistance )
83817466cbSJens Wiklander {
84817466cbSJens Wiklander     ctx->prediction_resistance = resistance;
85817466cbSJens Wiklander }
86817466cbSJens Wiklander 
8711fa71b9SJerome Forissier void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx,
8811fa71b9SJerome Forissier                                        size_t len )
89817466cbSJens Wiklander {
90817466cbSJens Wiklander     ctx->entropy_len = len;
91817466cbSJens Wiklander }
92817466cbSJens Wiklander 
9311fa71b9SJerome Forissier int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx,
9411fa71b9SJerome Forissier                                     size_t len )
9511fa71b9SJerome Forissier {
9611fa71b9SJerome Forissier     /* If mbedtls_ctr_drbg_seed() has already been called, it's
9711fa71b9SJerome Forissier      * too late. Return the error code that's closest to making sense. */
9811fa71b9SJerome Forissier     if( ctx->f_entropy != NULL )
9911fa71b9SJerome Forissier         return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
10011fa71b9SJerome Forissier 
10111fa71b9SJerome Forissier     if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
10211fa71b9SJerome Forissier         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
10311fa71b9SJerome Forissier #if SIZE_MAX > INT_MAX
10411fa71b9SJerome Forissier     /* This shouldn't be an issue because
10511fa71b9SJerome Forissier      * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible
10611fa71b9SJerome Forissier      * configuration, but make sure anyway. */
10711fa71b9SJerome Forissier     if( len > INT_MAX )
10811fa71b9SJerome Forissier         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
10911fa71b9SJerome Forissier #endif
11011fa71b9SJerome Forissier 
11111fa71b9SJerome Forissier     /* For backward compatibility with Mbed TLS <= 2.19, store the
11211fa71b9SJerome Forissier      * entropy nonce length in a field that already exists, but isn't
11311fa71b9SJerome Forissier      * used until after the initial seeding. */
11411fa71b9SJerome Forissier     /* Due to the capping of len above, the value fits in an int. */
11511fa71b9SJerome Forissier     ctx->reseed_counter = (int) len;
11611fa71b9SJerome Forissier     return( 0 );
11711fa71b9SJerome Forissier }
11811fa71b9SJerome Forissier 
11911fa71b9SJerome Forissier void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx,
12011fa71b9SJerome Forissier                                            int interval )
121817466cbSJens Wiklander {
122817466cbSJens Wiklander     ctx->reseed_interval = interval;
123817466cbSJens Wiklander }
124817466cbSJens Wiklander 
125817466cbSJens Wiklander static int block_cipher_df( unsigned char *output,
126817466cbSJens Wiklander                             const unsigned char *data, size_t data_len )
127817466cbSJens Wiklander {
12811fa71b9SJerome Forissier     unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
12911fa71b9SJerome Forissier                       MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
130817466cbSJens Wiklander     unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
131817466cbSJens Wiklander     unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
132817466cbSJens Wiklander     unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
133817466cbSJens Wiklander     unsigned char *p, *iv;
134817466cbSJens Wiklander     mbedtls_aes_context aes_ctx;
1353d3b0591SJens Wiklander     int ret = 0;
136817466cbSJens Wiklander 
137817466cbSJens Wiklander     int i, j;
138817466cbSJens Wiklander     size_t buf_len, use_len;
139817466cbSJens Wiklander 
140817466cbSJens Wiklander     if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
141817466cbSJens Wiklander         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
142817466cbSJens Wiklander 
14311fa71b9SJerome Forissier     memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
14411fa71b9SJerome Forissier             MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
145817466cbSJens Wiklander     mbedtls_aes_init( &aes_ctx );
146817466cbSJens Wiklander 
147817466cbSJens Wiklander     /*
148817466cbSJens Wiklander      * Construct IV (16 bytes) and S in buffer
149817466cbSJens Wiklander      * IV = Counter (in 32-bits) padded to 16 with zeroes
150817466cbSJens Wiklander      * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
151817466cbSJens Wiklander      *     data || 0x80
152817466cbSJens Wiklander      *     (Total is padded to a multiple of 16-bytes with zeroes)
153817466cbSJens Wiklander      */
154817466cbSJens Wiklander     p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
155817466cbSJens Wiklander     *p++ = ( data_len >> 24 ) & 0xff;
156817466cbSJens Wiklander     *p++ = ( data_len >> 16 ) & 0xff;
157817466cbSJens Wiklander     *p++ = ( data_len >> 8  ) & 0xff;
158817466cbSJens Wiklander     *p++ = ( data_len       ) & 0xff;
159817466cbSJens Wiklander     p += 3;
160817466cbSJens Wiklander     *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
161817466cbSJens Wiklander     memcpy( p, data, data_len );
162817466cbSJens Wiklander     p[data_len] = 0x80;
163817466cbSJens Wiklander 
164817466cbSJens Wiklander     buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
165817466cbSJens Wiklander 
166817466cbSJens Wiklander     for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
167817466cbSJens Wiklander         key[i] = i;
168817466cbSJens Wiklander 
16911fa71b9SJerome Forissier     if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key,
17011fa71b9SJerome Forissier                                         MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
1713d3b0591SJens Wiklander     {
1723d3b0591SJens Wiklander         goto exit;
1733d3b0591SJens Wiklander     }
174817466cbSJens Wiklander 
175817466cbSJens Wiklander     /*
176817466cbSJens Wiklander      * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
177817466cbSJens Wiklander      */
178817466cbSJens Wiklander     for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
179817466cbSJens Wiklander     {
180817466cbSJens Wiklander         p = buf;
181817466cbSJens Wiklander         memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
182817466cbSJens Wiklander         use_len = buf_len;
183817466cbSJens Wiklander 
184817466cbSJens Wiklander         while( use_len > 0 )
185817466cbSJens Wiklander         {
186817466cbSJens Wiklander             for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
187817466cbSJens Wiklander                 chain[i] ^= p[i];
188817466cbSJens Wiklander             p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
189817466cbSJens Wiklander             use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
190817466cbSJens Wiklander                        MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
191817466cbSJens Wiklander 
19211fa71b9SJerome Forissier             if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
19311fa71b9SJerome Forissier                                                chain, chain ) ) != 0 )
1943d3b0591SJens Wiklander             {
1953d3b0591SJens Wiklander                 goto exit;
1963d3b0591SJens Wiklander             }
197817466cbSJens Wiklander         }
198817466cbSJens Wiklander 
199817466cbSJens Wiklander         memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
200817466cbSJens Wiklander 
201817466cbSJens Wiklander         /*
202817466cbSJens Wiklander          * Update IV
203817466cbSJens Wiklander          */
204817466cbSJens Wiklander         buf[3]++;
205817466cbSJens Wiklander     }
206817466cbSJens Wiklander 
207817466cbSJens Wiklander     /*
208817466cbSJens Wiklander      * Do final encryption with reduced data
209817466cbSJens Wiklander      */
21011fa71b9SJerome Forissier     if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp,
21111fa71b9SJerome Forissier                                         MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
2123d3b0591SJens Wiklander     {
2133d3b0591SJens Wiklander         goto exit;
2143d3b0591SJens Wiklander     }
215817466cbSJens Wiklander     iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
216817466cbSJens Wiklander     p = output;
217817466cbSJens Wiklander 
218817466cbSJens Wiklander     for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
219817466cbSJens Wiklander     {
22011fa71b9SJerome Forissier         if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
22111fa71b9SJerome Forissier                                            iv, iv ) ) != 0 )
2223d3b0591SJens Wiklander         {
2233d3b0591SJens Wiklander             goto exit;
2243d3b0591SJens Wiklander         }
225817466cbSJens Wiklander         memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
226817466cbSJens Wiklander         p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
227817466cbSJens Wiklander     }
2283d3b0591SJens Wiklander exit:
229817466cbSJens Wiklander     mbedtls_aes_free( &aes_ctx );
2303d3b0591SJens Wiklander     /*
2313d3b0591SJens Wiklander     * tidy up the stack
2323d3b0591SJens Wiklander     */
2333d3b0591SJens Wiklander     mbedtls_platform_zeroize( buf, sizeof( buf ) );
2343d3b0591SJens Wiklander     mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
2353d3b0591SJens Wiklander     mbedtls_platform_zeroize( key, sizeof( key ) );
2363d3b0591SJens Wiklander     mbedtls_platform_zeroize( chain, sizeof( chain ) );
2373d3b0591SJens Wiklander     if( 0 != ret )
2383d3b0591SJens Wiklander     {
2393d3b0591SJens Wiklander         /*
2403d3b0591SJens Wiklander         * wipe partial seed from memory
2413d3b0591SJens Wiklander         */
2423d3b0591SJens Wiklander         mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
243817466cbSJens Wiklander     }
244817466cbSJens Wiklander 
2453d3b0591SJens Wiklander     return( ret );
2463d3b0591SJens Wiklander }
2473d3b0591SJens Wiklander 
2483d3b0591SJens Wiklander /* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
2493d3b0591SJens Wiklander  * ctr_drbg_update_internal(ctx, provided_data)
2503d3b0591SJens Wiklander  * implements
2513d3b0591SJens Wiklander  * CTR_DRBG_Update(provided_data, Key, V)
2523d3b0591SJens Wiklander  * with inputs and outputs
2533d3b0591SJens Wiklander  *   ctx->aes_ctx = Key
2543d3b0591SJens Wiklander  *   ctx->counter = V
2553d3b0591SJens Wiklander  */
256817466cbSJens Wiklander static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
257817466cbSJens Wiklander                           const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
258817466cbSJens Wiklander {
259817466cbSJens Wiklander     unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
260817466cbSJens Wiklander     unsigned char *p = tmp;
261817466cbSJens Wiklander     int i, j;
2623d3b0591SJens Wiklander     int ret = 0;
263817466cbSJens Wiklander 
264817466cbSJens Wiklander     memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
265817466cbSJens Wiklander 
266817466cbSJens Wiklander     for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
267817466cbSJens Wiklander     {
268817466cbSJens Wiklander         /*
269817466cbSJens Wiklander          * Increase counter
270817466cbSJens Wiklander          */
271817466cbSJens Wiklander         for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
272817466cbSJens Wiklander             if( ++ctx->counter[i - 1] != 0 )
273817466cbSJens Wiklander                 break;
274817466cbSJens Wiklander 
275817466cbSJens Wiklander         /*
276817466cbSJens Wiklander          * Crypt counter block
277817466cbSJens Wiklander          */
27811fa71b9SJerome Forissier         if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
27911fa71b9SJerome Forissier                                            ctx->counter, p ) ) != 0 )
28011fa71b9SJerome Forissier         {
2813d3b0591SJens Wiklander             goto exit;
28211fa71b9SJerome Forissier         }
283817466cbSJens Wiklander 
284817466cbSJens Wiklander         p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
285817466cbSJens Wiklander     }
286817466cbSJens Wiklander 
287817466cbSJens Wiklander     for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
288817466cbSJens Wiklander         tmp[i] ^= data[i];
289817466cbSJens Wiklander 
290817466cbSJens Wiklander     /*
291817466cbSJens Wiklander      * Update key and counter
292817466cbSJens Wiklander      */
29311fa71b9SJerome Forissier     if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp,
29411fa71b9SJerome Forissier                                         MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
29511fa71b9SJerome Forissier     {
2963d3b0591SJens Wiklander         goto exit;
29711fa71b9SJerome Forissier     }
29811fa71b9SJerome Forissier     memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
29911fa71b9SJerome Forissier             MBEDTLS_CTR_DRBG_BLOCKSIZE );
300817466cbSJens Wiklander 
3013d3b0591SJens Wiklander exit:
3023d3b0591SJens Wiklander     mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
3033d3b0591SJens Wiklander     return( ret );
304817466cbSJens Wiklander }
305817466cbSJens Wiklander 
3063d3b0591SJens Wiklander /* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
3073d3b0591SJens Wiklander  * mbedtls_ctr_drbg_update(ctx, additional, add_len)
3083d3b0591SJens Wiklander  * implements
3093d3b0591SJens Wiklander  * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
3103d3b0591SJens Wiklander  *                      security_strength) -> initial_working_state
3113d3b0591SJens Wiklander  * with inputs
3123d3b0591SJens Wiklander  *   ctx->counter = all-bits-0
3133d3b0591SJens Wiklander  *   ctx->aes_ctx = context from all-bits-0 key
3143d3b0591SJens Wiklander  *   additional[:add_len] = entropy_input || nonce || personalization_string
3153d3b0591SJens Wiklander  * and with outputs
3163d3b0591SJens Wiklander  *   ctx = initial_working_state
3173d3b0591SJens Wiklander  */
3183d3b0591SJens Wiklander int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
3193d3b0591SJens Wiklander                                  const unsigned char *additional,
3203d3b0591SJens Wiklander                                  size_t add_len )
321817466cbSJens Wiklander {
322817466cbSJens Wiklander     unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
32311fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
324817466cbSJens Wiklander 
3253d3b0591SJens Wiklander     if( add_len == 0 )
3263d3b0591SJens Wiklander         return( 0 );
3273d3b0591SJens Wiklander 
3283d3b0591SJens Wiklander     if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
3293d3b0591SJens Wiklander         goto exit;
3303d3b0591SJens Wiklander     if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
3313d3b0591SJens Wiklander         goto exit;
3323d3b0591SJens Wiklander 
3333d3b0591SJens Wiklander exit:
3343d3b0591SJens Wiklander     mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
3353d3b0591SJens Wiklander     return( ret );
3363d3b0591SJens Wiklander }
3373d3b0591SJens Wiklander 
3383d3b0591SJens Wiklander #if !defined(MBEDTLS_DEPRECATED_REMOVED)
3393d3b0591SJens Wiklander void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
3403d3b0591SJens Wiklander                               const unsigned char *additional,
3413d3b0591SJens Wiklander                               size_t add_len )
342817466cbSJens Wiklander {
343817466cbSJens Wiklander     /* MAX_INPUT would be more logical here, but we have to match
344817466cbSJens Wiklander      * block_cipher_df()'s limits since we can't propagate errors */
345817466cbSJens Wiklander     if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
346817466cbSJens Wiklander         add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
3473d3b0591SJens Wiklander     (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
348817466cbSJens Wiklander }
3493d3b0591SJens Wiklander #endif /* MBEDTLS_DEPRECATED_REMOVED */
350817466cbSJens Wiklander 
3513d3b0591SJens Wiklander /* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
35211fa71b9SJerome Forissier  * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
3533d3b0591SJens Wiklander  * implements
3543d3b0591SJens Wiklander  * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
3553d3b0591SJens Wiklander  *                -> new_working_state
3563d3b0591SJens Wiklander  * with inputs
3573d3b0591SJens Wiklander  *   ctx contains working_state
3583d3b0591SJens Wiklander  *   additional[:len] = additional_input
3593d3b0591SJens Wiklander  * and entropy_input comes from calling ctx->f_entropy
36011fa71b9SJerome Forissier  *                              for (ctx->entropy_len + nonce_len) bytes
3613d3b0591SJens Wiklander  * and with output
3623d3b0591SJens Wiklander  *   ctx contains new_working_state
3633d3b0591SJens Wiklander  */
36411fa71b9SJerome Forissier static int mbedtls_ctr_drbg_reseed_internal( mbedtls_ctr_drbg_context *ctx,
36511fa71b9SJerome Forissier                                              const unsigned char *additional,
36611fa71b9SJerome Forissier                                              size_t len,
36711fa71b9SJerome Forissier                                              size_t nonce_len )
368817466cbSJens Wiklander {
369817466cbSJens Wiklander     unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
370817466cbSJens Wiklander     size_t seedlen = 0;
37111fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
372817466cbSJens Wiklander 
37311fa71b9SJerome Forissier     if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
37411fa71b9SJerome Forissier         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
37511fa71b9SJerome Forissier     if( nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
37611fa71b9SJerome Forissier         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
37711fa71b9SJerome Forissier     if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len )
378817466cbSJens Wiklander         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
379817466cbSJens Wiklander 
380817466cbSJens Wiklander     memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
381817466cbSJens Wiklander 
38211fa71b9SJerome Forissier     /* Gather entropy_len bytes of entropy to seed state. */
38311fa71b9SJerome Forissier     if( 0 != ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) )
384817466cbSJens Wiklander     {
385817466cbSJens Wiklander         return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
386817466cbSJens Wiklander     }
387817466cbSJens Wiklander     seedlen += ctx->entropy_len;
388817466cbSJens Wiklander 
38911fa71b9SJerome Forissier     /* Gather entropy for a nonce if requested. */
39011fa71b9SJerome Forissier     if( nonce_len != 0 )
39111fa71b9SJerome Forissier     {
392*7901324dSJerome Forissier         if( 0 != ctx->f_entropy( ctx->p_entropy, seed + seedlen, nonce_len ) )
39311fa71b9SJerome Forissier         {
39411fa71b9SJerome Forissier             return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
39511fa71b9SJerome Forissier         }
39611fa71b9SJerome Forissier         seedlen += nonce_len;
39711fa71b9SJerome Forissier     }
39811fa71b9SJerome Forissier 
39911fa71b9SJerome Forissier     /* Add additional data if provided. */
40011fa71b9SJerome Forissier     if( additional != NULL && len != 0 )
401817466cbSJens Wiklander     {
402817466cbSJens Wiklander         memcpy( seed + seedlen, additional, len );
403817466cbSJens Wiklander         seedlen += len;
404817466cbSJens Wiklander     }
405817466cbSJens Wiklander 
40611fa71b9SJerome Forissier     /* Reduce to 384 bits. */
4073d3b0591SJens Wiklander     if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
4083d3b0591SJens Wiklander         goto exit;
409817466cbSJens Wiklander 
41011fa71b9SJerome Forissier     /* Update state. */
4113d3b0591SJens Wiklander     if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
4123d3b0591SJens Wiklander         goto exit;
413817466cbSJens Wiklander     ctx->reseed_counter = 1;
414817466cbSJens Wiklander 
4153d3b0591SJens Wiklander exit:
4163d3b0591SJens Wiklander     mbedtls_platform_zeroize( seed, sizeof( seed ) );
4173d3b0591SJens Wiklander     return( ret );
418817466cbSJens Wiklander }
419817466cbSJens Wiklander 
42011fa71b9SJerome Forissier int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
42111fa71b9SJerome Forissier                              const unsigned char *additional, size_t len )
42211fa71b9SJerome Forissier {
42311fa71b9SJerome Forissier     return( mbedtls_ctr_drbg_reseed_internal( ctx, additional, len, 0 ) );
42411fa71b9SJerome Forissier }
42511fa71b9SJerome Forissier 
42611fa71b9SJerome Forissier /* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
42711fa71b9SJerome Forissier  * is sufficient to achieve the maximum security strength given the key
42811fa71b9SJerome Forissier  * size and entropy length. If there is enough entropy in the initial
42911fa71b9SJerome Forissier  * call to the entropy function to serve as both the entropy input and
43011fa71b9SJerome Forissier  * the nonce, don't make a second call to get a nonce. */
43111fa71b9SJerome Forissier static size_t good_nonce_len( size_t entropy_len )
43211fa71b9SJerome Forissier {
43311fa71b9SJerome Forissier     if( entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 )
43411fa71b9SJerome Forissier         return( 0 );
43511fa71b9SJerome Forissier     else
43611fa71b9SJerome Forissier         return( ( entropy_len + 1 ) / 2 );
43711fa71b9SJerome Forissier }
43811fa71b9SJerome Forissier 
4395b25c76aSJerome Forissier /* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
4405b25c76aSJerome Forissier  * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
4415b25c76aSJerome Forissier  * implements
4425b25c76aSJerome Forissier  * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
4435b25c76aSJerome Forissier  *                      security_strength) -> initial_working_state
4445b25c76aSJerome Forissier  * with inputs
4455b25c76aSJerome Forissier  *   custom[:len] = nonce || personalization_string
4465b25c76aSJerome Forissier  * where entropy_input comes from f_entropy for ctx->entropy_len bytes
4475b25c76aSJerome Forissier  * and with outputs
4485b25c76aSJerome Forissier  *   ctx = initial_working_state
4495b25c76aSJerome Forissier  */
4505b25c76aSJerome Forissier int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
4515b25c76aSJerome Forissier                            int (*f_entropy)(void *, unsigned char *, size_t),
4525b25c76aSJerome Forissier                            void *p_entropy,
4535b25c76aSJerome Forissier                            const unsigned char *custom,
4545b25c76aSJerome Forissier                            size_t len )
4555b25c76aSJerome Forissier {
45611fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
4575b25c76aSJerome Forissier     unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
45811fa71b9SJerome Forissier     size_t nonce_len;
4595b25c76aSJerome Forissier 
4605b25c76aSJerome Forissier     memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
4615b25c76aSJerome Forissier 
462*7901324dSJerome Forissier     /* The mutex is initialized iff f_entropy is set. */
463*7901324dSJerome Forissier #if defined(MBEDTLS_THREADING_C)
464*7901324dSJerome Forissier     mbedtls_mutex_init( &ctx->mutex );
465*7901324dSJerome Forissier #endif
466*7901324dSJerome Forissier 
4675b25c76aSJerome Forissier     mbedtls_aes_init( &ctx->aes_ctx );
4685b25c76aSJerome Forissier 
4695b25c76aSJerome Forissier     ctx->f_entropy = f_entropy;
4705b25c76aSJerome Forissier     ctx->p_entropy = p_entropy;
4715b25c76aSJerome Forissier 
4725b25c76aSJerome Forissier     if( ctx->entropy_len == 0 )
4735b25c76aSJerome Forissier         ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
47411fa71b9SJerome Forissier     /* ctx->reseed_counter contains the desired amount of entropy to
47511fa71b9SJerome Forissier      * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
47611fa71b9SJerome Forissier      * If it's -1, indicating that the entropy nonce length was not set
47711fa71b9SJerome Forissier      * explicitly, use a sufficiently large nonce for security. */
47811fa71b9SJerome Forissier     nonce_len = ( ctx->reseed_counter >= 0 ?
47911fa71b9SJerome Forissier                   (size_t) ctx->reseed_counter :
48011fa71b9SJerome Forissier                   good_nonce_len( ctx->entropy_len ) );
48111fa71b9SJerome Forissier 
48211fa71b9SJerome Forissier     /* Initialize with an empty key. */
48311fa71b9SJerome Forissier     if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
48411fa71b9SJerome Forissier                                         MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
4855b25c76aSJerome Forissier     {
4865b25c76aSJerome Forissier         return( ret );
4875b25c76aSJerome Forissier     }
4885b25c76aSJerome Forissier 
48911fa71b9SJerome Forissier     /* Do the initial seeding. */
49011fa71b9SJerome Forissier     if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len,
49111fa71b9SJerome Forissier                                                   nonce_len ) ) != 0 )
4925b25c76aSJerome Forissier     {
4935b25c76aSJerome Forissier         return( ret );
4945b25c76aSJerome Forissier     }
4955b25c76aSJerome Forissier     return( 0 );
4965b25c76aSJerome Forissier }
4975b25c76aSJerome Forissier 
4983d3b0591SJens Wiklander /* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
4993d3b0591SJens Wiklander  * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
5003d3b0591SJens Wiklander  * implements
5013d3b0591SJens Wiklander  * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
5023d3b0591SJens Wiklander  *                -> working_state_after_reseed
5033d3b0591SJens Wiklander  *                if required, then
5043d3b0591SJens Wiklander  * CTR_DRBG_Generate(working_state_after_reseed,
5053d3b0591SJens Wiklander  *                   requested_number_of_bits, additional_input)
5063d3b0591SJens Wiklander  *                -> status, returned_bits, new_working_state
5073d3b0591SJens Wiklander  * with inputs
5083d3b0591SJens Wiklander  *   ctx contains working_state
5093d3b0591SJens Wiklander  *   requested_number_of_bits = 8 * output_len
5103d3b0591SJens Wiklander  *   additional[:add_len] = additional_input
5113d3b0591SJens Wiklander  * and entropy_input comes from calling ctx->f_entropy
5123d3b0591SJens Wiklander  * and with outputs
5133d3b0591SJens Wiklander  *   status = SUCCESS (this function does the reseed internally)
5143d3b0591SJens Wiklander  *   returned_bits = output[:output_len]
5153d3b0591SJens Wiklander  *   ctx contains new_working_state
5163d3b0591SJens Wiklander  */
517817466cbSJens Wiklander int mbedtls_ctr_drbg_random_with_add( void *p_rng,
518817466cbSJens Wiklander                               unsigned char *output, size_t output_len,
519817466cbSJens Wiklander                               const unsigned char *additional, size_t add_len )
520817466cbSJens Wiklander {
521817466cbSJens Wiklander     int ret = 0;
522817466cbSJens Wiklander     mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
523817466cbSJens Wiklander     unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
524817466cbSJens Wiklander     unsigned char *p = output;
525817466cbSJens Wiklander     unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
526817466cbSJens Wiklander     int i;
527817466cbSJens Wiklander     size_t use_len;
528817466cbSJens Wiklander 
529817466cbSJens Wiklander     if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
530817466cbSJens Wiklander         return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
531817466cbSJens Wiklander 
532817466cbSJens Wiklander     if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
533817466cbSJens Wiklander         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
534817466cbSJens Wiklander 
535817466cbSJens Wiklander     memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
536817466cbSJens Wiklander 
537817466cbSJens Wiklander     if( ctx->reseed_counter > ctx->reseed_interval ||
538817466cbSJens Wiklander         ctx->prediction_resistance )
539817466cbSJens Wiklander     {
540817466cbSJens Wiklander         if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
5413d3b0591SJens Wiklander         {
542817466cbSJens Wiklander             return( ret );
5433d3b0591SJens Wiklander         }
544817466cbSJens Wiklander         add_len = 0;
545817466cbSJens Wiklander     }
546817466cbSJens Wiklander 
547817466cbSJens Wiklander     if( add_len > 0 )
548817466cbSJens Wiklander     {
5493d3b0591SJens Wiklander         if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
5503d3b0591SJens Wiklander             goto exit;
5513d3b0591SJens Wiklander         if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
5523d3b0591SJens Wiklander             goto exit;
553817466cbSJens Wiklander     }
554817466cbSJens Wiklander 
555817466cbSJens Wiklander     while( output_len > 0 )
556817466cbSJens Wiklander     {
557817466cbSJens Wiklander         /*
558817466cbSJens Wiklander          * Increase counter
559817466cbSJens Wiklander          */
560817466cbSJens Wiklander         for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
561817466cbSJens Wiklander             if( ++ctx->counter[i - 1] != 0 )
562817466cbSJens Wiklander                 break;
563817466cbSJens Wiklander 
564817466cbSJens Wiklander         /*
565817466cbSJens Wiklander          * Crypt counter block
566817466cbSJens Wiklander          */
56711fa71b9SJerome Forissier         if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
56811fa71b9SJerome Forissier                                            ctx->counter, tmp ) ) != 0 )
56911fa71b9SJerome Forissier         {
5703d3b0591SJens Wiklander             goto exit;
57111fa71b9SJerome Forissier         }
572817466cbSJens Wiklander 
57311fa71b9SJerome Forissier         use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE )
57411fa71b9SJerome Forissier             ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
575817466cbSJens Wiklander         /*
576817466cbSJens Wiklander          * Copy random block to destination
577817466cbSJens Wiklander          */
578817466cbSJens Wiklander         memcpy( p, tmp, use_len );
579817466cbSJens Wiklander         p += use_len;
580817466cbSJens Wiklander         output_len -= use_len;
581817466cbSJens Wiklander     }
582817466cbSJens Wiklander 
5833d3b0591SJens Wiklander     if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
5843d3b0591SJens Wiklander         goto exit;
585817466cbSJens Wiklander 
586817466cbSJens Wiklander     ctx->reseed_counter++;
587817466cbSJens Wiklander 
5883d3b0591SJens Wiklander exit:
5893d3b0591SJens Wiklander     mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
5903d3b0591SJens Wiklander     mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
5915b25c76aSJerome Forissier     return( ret );
592817466cbSJens Wiklander }
593817466cbSJens Wiklander 
59411fa71b9SJerome Forissier int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output,
59511fa71b9SJerome Forissier                              size_t output_len )
596817466cbSJens Wiklander {
59711fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
598817466cbSJens Wiklander     mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
599817466cbSJens Wiklander 
600817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C)
601817466cbSJens Wiklander     if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
602817466cbSJens Wiklander         return( ret );
603817466cbSJens Wiklander #endif
604817466cbSJens Wiklander 
605817466cbSJens Wiklander     ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
606817466cbSJens Wiklander 
607817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C)
608817466cbSJens Wiklander     if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
609817466cbSJens Wiklander         return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
610817466cbSJens Wiklander #endif
611817466cbSJens Wiklander 
612817466cbSJens Wiklander     return( ret );
613817466cbSJens Wiklander }
614817466cbSJens Wiklander 
615817466cbSJens Wiklander #if defined(MBEDTLS_FS_IO)
61611fa71b9SJerome Forissier int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx,
61711fa71b9SJerome Forissier                                       const char *path )
618817466cbSJens Wiklander {
619817466cbSJens Wiklander     int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
620817466cbSJens Wiklander     FILE *f;
621817466cbSJens Wiklander     unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
622817466cbSJens Wiklander 
623817466cbSJens Wiklander     if( ( f = fopen( path, "wb" ) ) == NULL )
624817466cbSJens Wiklander         return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
625817466cbSJens Wiklander 
62611fa71b9SJerome Forissier     if( ( ret = mbedtls_ctr_drbg_random( ctx, buf,
62711fa71b9SJerome Forissier                                          MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
628817466cbSJens Wiklander         goto exit;
629817466cbSJens Wiklander 
63011fa71b9SJerome Forissier     if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) !=
63111fa71b9SJerome Forissier         MBEDTLS_CTR_DRBG_MAX_INPUT )
63211fa71b9SJerome Forissier     {
633817466cbSJens Wiklander         ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
63411fa71b9SJerome Forissier     }
6353d3b0591SJens Wiklander     else
63611fa71b9SJerome Forissier     {
637817466cbSJens Wiklander         ret = 0;
63811fa71b9SJerome Forissier     }
639817466cbSJens Wiklander 
640817466cbSJens Wiklander exit:
6413d3b0591SJens Wiklander     mbedtls_platform_zeroize( buf, sizeof( buf ) );
6423d3b0591SJens Wiklander 
643817466cbSJens Wiklander     fclose( f );
644817466cbSJens Wiklander     return( ret );
645817466cbSJens Wiklander }
646817466cbSJens Wiklander 
64711fa71b9SJerome Forissier int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx,
64811fa71b9SJerome Forissier                                        const char *path )
649817466cbSJens Wiklander {
6503d3b0591SJens Wiklander     int ret = 0;
6513d3b0591SJens Wiklander     FILE *f = NULL;
652817466cbSJens Wiklander     size_t n;
653817466cbSJens Wiklander     unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
6543d3b0591SJens Wiklander     unsigned char c;
655817466cbSJens Wiklander 
656817466cbSJens Wiklander     if( ( f = fopen( path, "rb" ) ) == NULL )
657817466cbSJens Wiklander         return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
658817466cbSJens Wiklander 
6593d3b0591SJens Wiklander     n = fread( buf, 1, sizeof( buf ), f );
6603d3b0591SJens Wiklander     if( fread( &c, 1, 1, f ) != 0 )
661817466cbSJens Wiklander     {
6623d3b0591SJens Wiklander         ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
6633d3b0591SJens Wiklander         goto exit;
664817466cbSJens Wiklander     }
6653d3b0591SJens Wiklander     if( n == 0 || ferror( f ) )
666817466cbSJens Wiklander     {
6673d3b0591SJens Wiklander         ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
6683d3b0591SJens Wiklander         goto exit;
669817466cbSJens Wiklander     }
670817466cbSJens Wiklander     fclose( f );
6713d3b0591SJens Wiklander     f = NULL;
672817466cbSJens Wiklander 
6733d3b0591SJens Wiklander     ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
674817466cbSJens Wiklander 
6753d3b0591SJens Wiklander exit:
6763d3b0591SJens Wiklander     mbedtls_platform_zeroize( buf, sizeof( buf ) );
6773d3b0591SJens Wiklander     if( f != NULL )
6783d3b0591SJens Wiklander         fclose( f );
6793d3b0591SJens Wiklander     if( ret != 0 )
6803d3b0591SJens Wiklander         return( ret );
681817466cbSJens Wiklander     return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
682817466cbSJens Wiklander }
683817466cbSJens Wiklander #endif /* MBEDTLS_FS_IO */
684817466cbSJens Wiklander 
685817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST)
686817466cbSJens Wiklander 
687*7901324dSJerome Forissier /* The CTR_DRBG NIST test vectors used here are available at
688*7901324dSJerome Forissier  * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip
689*7901324dSJerome Forissier  *
690*7901324dSJerome Forissier  * The parameters used to derive the test data are:
691*7901324dSJerome Forissier  *
692*7901324dSJerome Forissier  * [AES-128 use df]
693*7901324dSJerome Forissier  * [PredictionResistance = True/False]
694*7901324dSJerome Forissier  * [EntropyInputLen = 128]
695*7901324dSJerome Forissier  * [NonceLen = 64]
696*7901324dSJerome Forissier  * [PersonalizationStringLen = 128]
697*7901324dSJerome Forissier  * [AdditionalInputLen = 0]
698*7901324dSJerome Forissier  * [ReturnedBitsLen = 512]
699*7901324dSJerome Forissier  *
700*7901324dSJerome Forissier  * [AES-256 use df]
701*7901324dSJerome Forissier  * [PredictionResistance = True/False]
702*7901324dSJerome Forissier  * [EntropyInputLen = 256]
703*7901324dSJerome Forissier  * [NonceLen = 128]
704*7901324dSJerome Forissier  * [PersonalizationStringLen = 256]
705*7901324dSJerome Forissier  * [AdditionalInputLen = 0]
706*7901324dSJerome Forissier  * [ReturnedBitsLen = 512]
707*7901324dSJerome Forissier  *
708*7901324dSJerome Forissier  */
709817466cbSJens Wiklander 
71011fa71b9SJerome Forissier #if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
711*7901324dSJerome Forissier static const unsigned char entropy_source_pr[] =
712*7901324dSJerome Forissier     { 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb,
713*7901324dSJerome Forissier       0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92,
714*7901324dSJerome Forissier       0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8,
715*7901324dSJerome Forissier       0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20,
716*7901324dSJerome Forissier       0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0,
717*7901324dSJerome Forissier       0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad,
718*7901324dSJerome Forissier       0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 };
71911fa71b9SJerome Forissier 
720*7901324dSJerome Forissier static const unsigned char entropy_source_nopr[] =
721*7901324dSJerome Forissier     { 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45,
722*7901324dSJerome Forissier       0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9,
723*7901324dSJerome Forissier       0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20,
724*7901324dSJerome Forissier       0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f,
725*7901324dSJerome Forissier       0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c };
726*7901324dSJerome Forissier 
727*7901324dSJerome Forissier static const unsigned char pers_pr[] =
728*7901324dSJerome Forissier     { 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a,
729*7901324dSJerome Forissier       0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad };
730*7901324dSJerome Forissier 
731*7901324dSJerome Forissier static const unsigned char pers_nopr[] =
732*7901324dSJerome Forissier     { 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c,
733*7901324dSJerome Forissier       0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f };
734*7901324dSJerome Forissier 
735*7901324dSJerome Forissier static const unsigned char result_pr[] =
736*7901324dSJerome Forissier     { 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66,
737*7901324dSJerome Forissier       0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff,
738*7901324dSJerome Forissier       0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10,
739*7901324dSJerome Forissier       0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30,
740*7901324dSJerome Forissier       0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4,
741*7901324dSJerome Forissier       0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc,
742*7901324dSJerome Forissier       0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06,
743*7901324dSJerome Forissier       0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf };
744*7901324dSJerome Forissier 
745*7901324dSJerome Forissier static const unsigned char result_nopr[] =
746*7901324dSJerome Forissier     { 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13,
747*7901324dSJerome Forissier       0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0,
748*7901324dSJerome Forissier       0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf,
749*7901324dSJerome Forissier       0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2,
750*7901324dSJerome Forissier       0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7,
751*7901324dSJerome Forissier       0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2,
752*7901324dSJerome Forissier       0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02,
753*7901324dSJerome Forissier       0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 };
75411fa71b9SJerome Forissier #else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
755817466cbSJens Wiklander 
756*7901324dSJerome Forissier static const unsigned char entropy_source_pr[] =
757*7901324dSJerome Forissier     { 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49,
758*7901324dSJerome Forissier       0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a,
759*7901324dSJerome Forissier       0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85,
760*7901324dSJerome Forissier       0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e,
761*7901324dSJerome Forissier       0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15,
762*7901324dSJerome Forissier       0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45,
763*7901324dSJerome Forissier       0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8,
764*7901324dSJerome Forissier       0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c,
765*7901324dSJerome Forissier       0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3,
766*7901324dSJerome Forissier       0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce,
767*7901324dSJerome Forissier       0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e,
768*7901324dSJerome Forissier       0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76,
769*7901324dSJerome Forissier       0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77,
770*7901324dSJerome Forissier       0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe };
771*7901324dSJerome Forissier 
772*7901324dSJerome Forissier static const unsigned char entropy_source_nopr[] =
773*7901324dSJerome Forissier     { 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d,
774*7901324dSJerome Forissier       0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0,
775*7901324dSJerome Forissier       0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73,
776*7901324dSJerome Forissier       0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c,
777*7901324dSJerome Forissier       0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2,
778*7901324dSJerome Forissier       0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1,
779*7901324dSJerome Forissier       0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a,
780*7901324dSJerome Forissier       0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb,
781*7901324dSJerome Forissier       0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a,
782*7901324dSJerome Forissier       0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 };
783*7901324dSJerome Forissier 
784*7901324dSJerome Forissier static const unsigned char pers_pr[] =
785*7901324dSJerome Forissier     { 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33,
786*7901324dSJerome Forissier       0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e,
787*7901324dSJerome Forissier       0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0,
788*7901324dSJerome Forissier       0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 };
789*7901324dSJerome Forissier 
790*7901324dSJerome Forissier static const unsigned char pers_nopr[] =
791*7901324dSJerome Forissier     { 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29,
792*7901324dSJerome Forissier       0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf,
793*7901324dSJerome Forissier       0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb,
794*7901324dSJerome Forissier       0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b };
795*7901324dSJerome Forissier 
796*7901324dSJerome Forissier static const unsigned char result_pr[] =
797*7901324dSJerome Forissier     { 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85,
798*7901324dSJerome Forissier       0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d,
799*7901324dSJerome Forissier       0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62,
800*7901324dSJerome Forissier       0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d,
801*7901324dSJerome Forissier       0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb,
802*7901324dSJerome Forissier       0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39,
803*7901324dSJerome Forissier       0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40,
804*7901324dSJerome Forissier       0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 };
805*7901324dSJerome Forissier 
806*7901324dSJerome Forissier static const unsigned char result_nopr[] =
807*7901324dSJerome Forissier     { 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad,
808*7901324dSJerome Forissier       0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3,
809*7901324dSJerome Forissier       0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b,
810*7901324dSJerome Forissier       0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14,
811*7901324dSJerome Forissier       0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54,
812*7901324dSJerome Forissier       0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30,
813*7901324dSJerome Forissier       0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a,
814*7901324dSJerome Forissier       0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 };
81511fa71b9SJerome Forissier #endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
816817466cbSJens Wiklander 
817817466cbSJens Wiklander static size_t test_offset;
818817466cbSJens Wiklander static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
819817466cbSJens Wiklander                                        size_t len )
820817466cbSJens Wiklander {
821817466cbSJens Wiklander     const unsigned char *p = data;
822817466cbSJens Wiklander     memcpy( buf, p + test_offset, len );
823817466cbSJens Wiklander     test_offset += len;
824817466cbSJens Wiklander     return( 0 );
825817466cbSJens Wiklander }
826817466cbSJens Wiklander 
827817466cbSJens Wiklander #define CHK( c )    if( (c) != 0 )                          \
828817466cbSJens Wiklander                     {                                       \
829817466cbSJens Wiklander                         if( verbose != 0 )                  \
830817466cbSJens Wiklander                             mbedtls_printf( "failed\n" );  \
831817466cbSJens Wiklander                         return( 1 );                        \
832817466cbSJens Wiklander                     }
833817466cbSJens Wiklander 
834*7901324dSJerome Forissier #define SELF_TEST_OUPUT_DISCARD_LENGTH 64
835*7901324dSJerome Forissier 
836817466cbSJens Wiklander /*
837817466cbSJens Wiklander  * Checkup routine
838817466cbSJens Wiklander  */
839817466cbSJens Wiklander int mbedtls_ctr_drbg_self_test( int verbose )
840817466cbSJens Wiklander {
841817466cbSJens Wiklander     mbedtls_ctr_drbg_context ctx;
842*7901324dSJerome Forissier     unsigned char buf[ sizeof( result_pr ) ];
843817466cbSJens Wiklander 
844817466cbSJens Wiklander     mbedtls_ctr_drbg_init( &ctx );
845817466cbSJens Wiklander 
846817466cbSJens Wiklander     /*
847817466cbSJens Wiklander      * Based on a NIST CTR_DRBG test vector (PR = True)
848817466cbSJens Wiklander      */
849817466cbSJens Wiklander     if( verbose != 0 )
850817466cbSJens Wiklander         mbedtls_printf( "  CTR_DRBG (PR = TRUE) : " );
851817466cbSJens Wiklander 
852817466cbSJens Wiklander     test_offset = 0;
853*7901324dSJerome Forissier     mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE );
854*7901324dSJerome Forissier     mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
8555b25c76aSJerome Forissier     CHK( mbedtls_ctr_drbg_seed( &ctx,
8565b25c76aSJerome Forissier                                 ctr_drbg_self_test_entropy,
8575b25c76aSJerome Forissier                                 (void *) entropy_source_pr,
858*7901324dSJerome Forissier                                 pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
859817466cbSJens Wiklander     mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
860*7901324dSJerome Forissier     CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUPUT_DISCARD_LENGTH ) );
861*7901324dSJerome Forissier     CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_pr ) ) );
862*7901324dSJerome Forissier     CHK( memcmp( buf, result_pr, sizeof( result_pr ) ) );
863817466cbSJens Wiklander 
864817466cbSJens Wiklander     mbedtls_ctr_drbg_free( &ctx );
865817466cbSJens Wiklander 
866817466cbSJens Wiklander     if( verbose != 0 )
867817466cbSJens Wiklander         mbedtls_printf( "passed\n" );
868817466cbSJens Wiklander 
869817466cbSJens Wiklander     /*
870817466cbSJens Wiklander      * Based on a NIST CTR_DRBG test vector (PR = FALSE)
871817466cbSJens Wiklander      */
872817466cbSJens Wiklander     if( verbose != 0 )
873817466cbSJens Wiklander         mbedtls_printf( "  CTR_DRBG (PR = FALSE): " );
874817466cbSJens Wiklander 
875817466cbSJens Wiklander     mbedtls_ctr_drbg_init( &ctx );
876817466cbSJens Wiklander 
877817466cbSJens Wiklander     test_offset = 0;
878*7901324dSJerome Forissier     mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
879*7901324dSJerome Forissier     mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
8805b25c76aSJerome Forissier     CHK( mbedtls_ctr_drbg_seed( &ctx,
8815b25c76aSJerome Forissier                                 ctr_drbg_self_test_entropy,
8825b25c76aSJerome Forissier                                 (void *) entropy_source_nopr,
883*7901324dSJerome Forissier                                 pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
884817466cbSJens Wiklander     CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
885*7901324dSJerome Forissier     CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUPUT_DISCARD_LENGTH ) );
886*7901324dSJerome Forissier     CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_nopr ) ) );
887*7901324dSJerome Forissier     CHK( memcmp( buf, result_nopr, sizeof( result_nopr ) ) );
888817466cbSJens Wiklander 
889817466cbSJens Wiklander     mbedtls_ctr_drbg_free( &ctx );
890817466cbSJens Wiklander 
891817466cbSJens Wiklander     if( verbose != 0 )
892817466cbSJens Wiklander         mbedtls_printf( "passed\n" );
893817466cbSJens Wiklander 
894817466cbSJens Wiklander     if( verbose != 0 )
895817466cbSJens Wiklander             mbedtls_printf( "\n" );
896817466cbSJens Wiklander 
897817466cbSJens Wiklander     return( 0 );
898817466cbSJens Wiklander }
899817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST */
900817466cbSJens Wiklander 
901817466cbSJens Wiklander #endif /* MBEDTLS_CTR_DRBG_C */
902