xref: /optee_os/lib/libmbedtls/mbedtls/library/ctr_drbg.c (revision 11fa71b9ddb429088f325cfda430183003ccd1db)
1c6672fdcSEdison Ai // SPDX-License-Identifier: Apache-2.0
2817466cbSJens Wiklander /*
3817466cbSJens Wiklander  *  CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
4817466cbSJens Wiklander  *
5817466cbSJens Wiklander  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
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  *  This file is part of mbed TLS (https://tls.mbed.org)
20817466cbSJens Wiklander  */
21817466cbSJens Wiklander /*
223d3b0591SJens Wiklander  *  The NIST SP 800-90 DRBGs are described in the following publication.
23817466cbSJens Wiklander  *
24817466cbSJens Wiklander  *  http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
25817466cbSJens Wiklander  */
26817466cbSJens Wiklander 
27817466cbSJens Wiklander #if !defined(MBEDTLS_CONFIG_FILE)
28817466cbSJens Wiklander #include "mbedtls/config.h"
29817466cbSJens Wiklander #else
30817466cbSJens Wiklander #include MBEDTLS_CONFIG_FILE
31817466cbSJens Wiklander #endif
32817466cbSJens Wiklander 
33817466cbSJens Wiklander #if defined(MBEDTLS_CTR_DRBG_C)
34817466cbSJens Wiklander 
35817466cbSJens Wiklander #include "mbedtls/ctr_drbg.h"
363d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
37*11fa71b9SJerome Forissier #include "mbedtls/error.h"
38817466cbSJens Wiklander 
39817466cbSJens Wiklander #include <string.h>
40817466cbSJens Wiklander 
41817466cbSJens Wiklander #if defined(MBEDTLS_FS_IO)
42817466cbSJens Wiklander #include <stdio.h>
43817466cbSJens Wiklander #endif
44817466cbSJens Wiklander 
45817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST)
46817466cbSJens Wiklander #if defined(MBEDTLS_PLATFORM_C)
47817466cbSJens Wiklander #include "mbedtls/platform.h"
48817466cbSJens Wiklander #else
49817466cbSJens Wiklander #include <stdio.h>
50817466cbSJens Wiklander #define mbedtls_printf printf
51817466cbSJens Wiklander #endif /* MBEDTLS_PLATFORM_C */
52817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST */
53817466cbSJens Wiklander 
54817466cbSJens Wiklander /*
55817466cbSJens Wiklander  * CTR_DRBG context initialization
56817466cbSJens Wiklander  */
57817466cbSJens Wiklander void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
58817466cbSJens Wiklander {
59817466cbSJens Wiklander     memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
60*11fa71b9SJerome Forissier     /* Indicate that the entropy nonce length is not set explicitly.
61*11fa71b9SJerome Forissier      * See mbedtls_ctr_drbg_set_nonce_len(). */
62*11fa71b9SJerome Forissier     ctx->reseed_counter = -1;
63817466cbSJens Wiklander 
64817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C)
65817466cbSJens Wiklander     mbedtls_mutex_init( &ctx->mutex );
66817466cbSJens Wiklander #endif
67817466cbSJens Wiklander }
68817466cbSJens Wiklander 
69817466cbSJens Wiklander void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
70817466cbSJens Wiklander {
71817466cbSJens Wiklander     if( ctx == NULL )
72817466cbSJens Wiklander         return;
73817466cbSJens Wiklander 
74817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C)
75817466cbSJens Wiklander     mbedtls_mutex_free( &ctx->mutex );
76817466cbSJens Wiklander #endif
77817466cbSJens Wiklander     mbedtls_aes_free( &ctx->aes_ctx );
783d3b0591SJens Wiklander     mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
79817466cbSJens Wiklander }
80817466cbSJens Wiklander 
81*11fa71b9SJerome Forissier void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx,
82*11fa71b9SJerome Forissier                                                  int resistance )
83817466cbSJens Wiklander {
84817466cbSJens Wiklander     ctx->prediction_resistance = resistance;
85817466cbSJens Wiklander }
86817466cbSJens Wiklander 
87*11fa71b9SJerome Forissier void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx,
88*11fa71b9SJerome Forissier                                        size_t len )
89817466cbSJens Wiklander {
90817466cbSJens Wiklander     ctx->entropy_len = len;
91817466cbSJens Wiklander }
92817466cbSJens Wiklander 
93*11fa71b9SJerome Forissier int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx,
94*11fa71b9SJerome Forissier                                     size_t len )
95*11fa71b9SJerome Forissier {
96*11fa71b9SJerome Forissier     /* If mbedtls_ctr_drbg_seed() has already been called, it's
97*11fa71b9SJerome Forissier      * too late. Return the error code that's closest to making sense. */
98*11fa71b9SJerome Forissier     if( ctx->f_entropy != NULL )
99*11fa71b9SJerome Forissier         return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
100*11fa71b9SJerome Forissier 
101*11fa71b9SJerome Forissier     if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
102*11fa71b9SJerome Forissier         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
103*11fa71b9SJerome Forissier #if SIZE_MAX > INT_MAX
104*11fa71b9SJerome Forissier     /* This shouldn't be an issue because
105*11fa71b9SJerome Forissier      * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible
106*11fa71b9SJerome Forissier      * configuration, but make sure anyway. */
107*11fa71b9SJerome Forissier     if( len > INT_MAX )
108*11fa71b9SJerome Forissier         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
109*11fa71b9SJerome Forissier #endif
110*11fa71b9SJerome Forissier 
111*11fa71b9SJerome Forissier     /* For backward compatibility with Mbed TLS <= 2.19, store the
112*11fa71b9SJerome Forissier      * entropy nonce length in a field that already exists, but isn't
113*11fa71b9SJerome Forissier      * used until after the initial seeding. */
114*11fa71b9SJerome Forissier     /* Due to the capping of len above, the value fits in an int. */
115*11fa71b9SJerome Forissier     ctx->reseed_counter = (int) len;
116*11fa71b9SJerome Forissier     return( 0 );
117*11fa71b9SJerome Forissier }
118*11fa71b9SJerome Forissier 
119*11fa71b9SJerome Forissier void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx,
120*11fa71b9SJerome 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 {
128*11fa71b9SJerome Forissier     unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
129*11fa71b9SJerome 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 
143*11fa71b9SJerome Forissier     memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
144*11fa71b9SJerome 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 
169*11fa71b9SJerome Forissier     if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key,
170*11fa71b9SJerome 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 
192*11fa71b9SJerome Forissier             if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
193*11fa71b9SJerome 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      */
210*11fa71b9SJerome Forissier     if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp,
211*11fa71b9SJerome 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     {
220*11fa71b9SJerome Forissier         if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
221*11fa71b9SJerome 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          */
278*11fa71b9SJerome Forissier         if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
279*11fa71b9SJerome Forissier                                            ctx->counter, p ) ) != 0 )
280*11fa71b9SJerome Forissier         {
2813d3b0591SJens Wiklander             goto exit;
282*11fa71b9SJerome 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      */
293*11fa71b9SJerome Forissier     if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp,
294*11fa71b9SJerome Forissier                                         MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
295*11fa71b9SJerome Forissier     {
2963d3b0591SJens Wiklander         goto exit;
297*11fa71b9SJerome Forissier     }
298*11fa71b9SJerome Forissier     memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
299*11fa71b9SJerome 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];
323*11fa71b9SJerome 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)
352*11fa71b9SJerome 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
360*11fa71b9SJerome Forissier  *                              for (ctx->entropy_len + nonce_len) bytes
3613d3b0591SJens Wiklander  * and with output
3623d3b0591SJens Wiklander  *   ctx contains new_working_state
3633d3b0591SJens Wiklander  */
364*11fa71b9SJerome Forissier static int mbedtls_ctr_drbg_reseed_internal( mbedtls_ctr_drbg_context *ctx,
365*11fa71b9SJerome Forissier                                              const unsigned char *additional,
366*11fa71b9SJerome Forissier                                              size_t len,
367*11fa71b9SJerome Forissier                                              size_t nonce_len )
368817466cbSJens Wiklander {
369817466cbSJens Wiklander     unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
370817466cbSJens Wiklander     size_t seedlen = 0;
371*11fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
372817466cbSJens Wiklander 
373*11fa71b9SJerome Forissier     if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
374*11fa71b9SJerome Forissier         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
375*11fa71b9SJerome Forissier     if( nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
376*11fa71b9SJerome Forissier         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
377*11fa71b9SJerome 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 
382*11fa71b9SJerome Forissier     /* Gather entropy_len bytes of entropy to seed state. */
383*11fa71b9SJerome 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 
389*11fa71b9SJerome Forissier     /* Gather entropy for a nonce if requested. */
390*11fa71b9SJerome Forissier     if( nonce_len != 0 )
391*11fa71b9SJerome Forissier     {
392*11fa71b9SJerome Forissier         if( 0 != ctx->f_entropy( ctx->p_entropy, seed, nonce_len ) )
393*11fa71b9SJerome Forissier         {
394*11fa71b9SJerome Forissier             return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
395*11fa71b9SJerome Forissier         }
396*11fa71b9SJerome Forissier         seedlen += nonce_len;
397*11fa71b9SJerome Forissier     }
398*11fa71b9SJerome Forissier 
399*11fa71b9SJerome Forissier     /* Add additional data if provided. */
400*11fa71b9SJerome Forissier     if( additional != NULL && len != 0 )
401817466cbSJens Wiklander     {
402817466cbSJens Wiklander         memcpy( seed + seedlen, additional, len );
403817466cbSJens Wiklander         seedlen += len;
404817466cbSJens Wiklander     }
405817466cbSJens Wiklander 
406*11fa71b9SJerome Forissier     /* Reduce to 384 bits. */
4073d3b0591SJens Wiklander     if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
4083d3b0591SJens Wiklander         goto exit;
409817466cbSJens Wiklander 
410*11fa71b9SJerome 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 
420*11fa71b9SJerome Forissier int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
421*11fa71b9SJerome Forissier                              const unsigned char *additional, size_t len )
422*11fa71b9SJerome Forissier {
423*11fa71b9SJerome Forissier     return( mbedtls_ctr_drbg_reseed_internal( ctx, additional, len, 0 ) );
424*11fa71b9SJerome Forissier }
425*11fa71b9SJerome Forissier 
426*11fa71b9SJerome Forissier /* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
427*11fa71b9SJerome Forissier  * is sufficient to achieve the maximum security strength given the key
428*11fa71b9SJerome Forissier  * size and entropy length. If there is enough entropy in the initial
429*11fa71b9SJerome Forissier  * call to the entropy function to serve as both the entropy input and
430*11fa71b9SJerome Forissier  * the nonce, don't make a second call to get a nonce. */
431*11fa71b9SJerome Forissier static size_t good_nonce_len( size_t entropy_len )
432*11fa71b9SJerome Forissier {
433*11fa71b9SJerome Forissier     if( entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 )
434*11fa71b9SJerome Forissier         return( 0 );
435*11fa71b9SJerome Forissier     else
436*11fa71b9SJerome Forissier         return( ( entropy_len + 1 ) / 2 );
437*11fa71b9SJerome Forissier }
438*11fa71b9SJerome 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 {
456*11fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
4575b25c76aSJerome Forissier     unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
458*11fa71b9SJerome Forissier     size_t nonce_len;
4595b25c76aSJerome Forissier 
4605b25c76aSJerome Forissier     memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
4615b25c76aSJerome Forissier 
4625b25c76aSJerome Forissier     mbedtls_aes_init( &ctx->aes_ctx );
4635b25c76aSJerome Forissier 
4645b25c76aSJerome Forissier     ctx->f_entropy = f_entropy;
4655b25c76aSJerome Forissier     ctx->p_entropy = p_entropy;
4665b25c76aSJerome Forissier 
4675b25c76aSJerome Forissier     if( ctx->entropy_len == 0 )
4685b25c76aSJerome Forissier         ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
469*11fa71b9SJerome Forissier     /* ctx->reseed_counter contains the desired amount of entropy to
470*11fa71b9SJerome Forissier      * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
471*11fa71b9SJerome Forissier      * If it's -1, indicating that the entropy nonce length was not set
472*11fa71b9SJerome Forissier      * explicitly, use a sufficiently large nonce for security. */
473*11fa71b9SJerome Forissier     nonce_len = ( ctx->reseed_counter >= 0 ?
474*11fa71b9SJerome Forissier                   (size_t) ctx->reseed_counter :
475*11fa71b9SJerome Forissier                   good_nonce_len( ctx->entropy_len ) );
476*11fa71b9SJerome Forissier 
4775b25c76aSJerome Forissier     ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
4785b25c76aSJerome Forissier 
479*11fa71b9SJerome Forissier     /* Initialize with an empty key. */
480*11fa71b9SJerome Forissier     if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
481*11fa71b9SJerome Forissier                                         MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
4825b25c76aSJerome Forissier     {
4835b25c76aSJerome Forissier         return( ret );
4845b25c76aSJerome Forissier     }
4855b25c76aSJerome Forissier 
486*11fa71b9SJerome Forissier     /* Do the initial seeding. */
487*11fa71b9SJerome Forissier     if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len,
488*11fa71b9SJerome Forissier                                                   nonce_len ) ) != 0 )
4895b25c76aSJerome Forissier     {
4905b25c76aSJerome Forissier         return( ret );
4915b25c76aSJerome Forissier     }
4925b25c76aSJerome Forissier     return( 0 );
4935b25c76aSJerome Forissier }
4945b25c76aSJerome Forissier 
4953d3b0591SJens Wiklander /* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
4963d3b0591SJens Wiklander  * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
4973d3b0591SJens Wiklander  * implements
4983d3b0591SJens Wiklander  * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
4993d3b0591SJens Wiklander  *                -> working_state_after_reseed
5003d3b0591SJens Wiklander  *                if required, then
5013d3b0591SJens Wiklander  * CTR_DRBG_Generate(working_state_after_reseed,
5023d3b0591SJens Wiklander  *                   requested_number_of_bits, additional_input)
5033d3b0591SJens Wiklander  *                -> status, returned_bits, new_working_state
5043d3b0591SJens Wiklander  * with inputs
5053d3b0591SJens Wiklander  *   ctx contains working_state
5063d3b0591SJens Wiklander  *   requested_number_of_bits = 8 * output_len
5073d3b0591SJens Wiklander  *   additional[:add_len] = additional_input
5083d3b0591SJens Wiklander  * and entropy_input comes from calling ctx->f_entropy
5093d3b0591SJens Wiklander  * and with outputs
5103d3b0591SJens Wiklander  *   status = SUCCESS (this function does the reseed internally)
5113d3b0591SJens Wiklander  *   returned_bits = output[:output_len]
5123d3b0591SJens Wiklander  *   ctx contains new_working_state
5133d3b0591SJens Wiklander  */
514817466cbSJens Wiklander int mbedtls_ctr_drbg_random_with_add( void *p_rng,
515817466cbSJens Wiklander                               unsigned char *output, size_t output_len,
516817466cbSJens Wiklander                               const unsigned char *additional, size_t add_len )
517817466cbSJens Wiklander {
518817466cbSJens Wiklander     int ret = 0;
519817466cbSJens Wiklander     mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
520817466cbSJens Wiklander     unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
521817466cbSJens Wiklander     unsigned char *p = output;
522817466cbSJens Wiklander     unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
523817466cbSJens Wiklander     int i;
524817466cbSJens Wiklander     size_t use_len;
525817466cbSJens Wiklander 
526817466cbSJens Wiklander     if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
527817466cbSJens Wiklander         return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
528817466cbSJens Wiklander 
529817466cbSJens Wiklander     if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
530817466cbSJens Wiklander         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
531817466cbSJens Wiklander 
532817466cbSJens Wiklander     memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
533817466cbSJens Wiklander 
534817466cbSJens Wiklander     if( ctx->reseed_counter > ctx->reseed_interval ||
535817466cbSJens Wiklander         ctx->prediction_resistance )
536817466cbSJens Wiklander     {
537817466cbSJens Wiklander         if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
5383d3b0591SJens Wiklander         {
539817466cbSJens Wiklander             return( ret );
5403d3b0591SJens Wiklander         }
541817466cbSJens Wiklander         add_len = 0;
542817466cbSJens Wiklander     }
543817466cbSJens Wiklander 
544817466cbSJens Wiklander     if( add_len > 0 )
545817466cbSJens Wiklander     {
5463d3b0591SJens Wiklander         if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
5473d3b0591SJens Wiklander             goto exit;
5483d3b0591SJens Wiklander         if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
5493d3b0591SJens Wiklander             goto exit;
550817466cbSJens Wiklander     }
551817466cbSJens Wiklander 
552817466cbSJens Wiklander     while( output_len > 0 )
553817466cbSJens Wiklander     {
554817466cbSJens Wiklander         /*
555817466cbSJens Wiklander          * Increase counter
556817466cbSJens Wiklander          */
557817466cbSJens Wiklander         for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
558817466cbSJens Wiklander             if( ++ctx->counter[i - 1] != 0 )
559817466cbSJens Wiklander                 break;
560817466cbSJens Wiklander 
561817466cbSJens Wiklander         /*
562817466cbSJens Wiklander          * Crypt counter block
563817466cbSJens Wiklander          */
564*11fa71b9SJerome Forissier         if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
565*11fa71b9SJerome Forissier                                            ctx->counter, tmp ) ) != 0 )
566*11fa71b9SJerome Forissier         {
5673d3b0591SJens Wiklander             goto exit;
568*11fa71b9SJerome Forissier         }
569817466cbSJens Wiklander 
570*11fa71b9SJerome Forissier         use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE )
571*11fa71b9SJerome Forissier             ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
572817466cbSJens Wiklander         /*
573817466cbSJens Wiklander          * Copy random block to destination
574817466cbSJens Wiklander          */
575817466cbSJens Wiklander         memcpy( p, tmp, use_len );
576817466cbSJens Wiklander         p += use_len;
577817466cbSJens Wiklander         output_len -= use_len;
578817466cbSJens Wiklander     }
579817466cbSJens Wiklander 
5803d3b0591SJens Wiklander     if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
5813d3b0591SJens Wiklander         goto exit;
582817466cbSJens Wiklander 
583817466cbSJens Wiklander     ctx->reseed_counter++;
584817466cbSJens Wiklander 
5853d3b0591SJens Wiklander exit:
5863d3b0591SJens Wiklander     mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
5873d3b0591SJens Wiklander     mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
5885b25c76aSJerome Forissier     return( ret );
589817466cbSJens Wiklander }
590817466cbSJens Wiklander 
591*11fa71b9SJerome Forissier int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output,
592*11fa71b9SJerome Forissier                              size_t output_len )
593817466cbSJens Wiklander {
594*11fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
595817466cbSJens Wiklander     mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
596817466cbSJens Wiklander 
597817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C)
598817466cbSJens Wiklander     if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
599817466cbSJens Wiklander         return( ret );
600817466cbSJens Wiklander #endif
601817466cbSJens Wiklander 
602817466cbSJens Wiklander     ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
603817466cbSJens Wiklander 
604817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C)
605817466cbSJens Wiklander     if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
606817466cbSJens Wiklander         return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
607817466cbSJens Wiklander #endif
608817466cbSJens Wiklander 
609817466cbSJens Wiklander     return( ret );
610817466cbSJens Wiklander }
611817466cbSJens Wiklander 
612817466cbSJens Wiklander #if defined(MBEDTLS_FS_IO)
613*11fa71b9SJerome Forissier int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx,
614*11fa71b9SJerome Forissier                                       const char *path )
615817466cbSJens Wiklander {
616817466cbSJens Wiklander     int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
617817466cbSJens Wiklander     FILE *f;
618817466cbSJens Wiklander     unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
619817466cbSJens Wiklander 
620817466cbSJens Wiklander     if( ( f = fopen( path, "wb" ) ) == NULL )
621817466cbSJens Wiklander         return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
622817466cbSJens Wiklander 
623*11fa71b9SJerome Forissier     if( ( ret = mbedtls_ctr_drbg_random( ctx, buf,
624*11fa71b9SJerome Forissier                                          MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
625817466cbSJens Wiklander         goto exit;
626817466cbSJens Wiklander 
627*11fa71b9SJerome Forissier     if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) !=
628*11fa71b9SJerome Forissier         MBEDTLS_CTR_DRBG_MAX_INPUT )
629*11fa71b9SJerome Forissier     {
630817466cbSJens Wiklander         ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
631*11fa71b9SJerome Forissier     }
6323d3b0591SJens Wiklander     else
633*11fa71b9SJerome Forissier     {
634817466cbSJens Wiklander         ret = 0;
635*11fa71b9SJerome Forissier     }
636817466cbSJens Wiklander 
637817466cbSJens Wiklander exit:
6383d3b0591SJens Wiklander     mbedtls_platform_zeroize( buf, sizeof( buf ) );
6393d3b0591SJens Wiklander 
640817466cbSJens Wiklander     fclose( f );
641817466cbSJens Wiklander     return( ret );
642817466cbSJens Wiklander }
643817466cbSJens Wiklander 
644*11fa71b9SJerome Forissier int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx,
645*11fa71b9SJerome Forissier                                        const char *path )
646817466cbSJens Wiklander {
6473d3b0591SJens Wiklander     int ret = 0;
6483d3b0591SJens Wiklander     FILE *f = NULL;
649817466cbSJens Wiklander     size_t n;
650817466cbSJens Wiklander     unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
6513d3b0591SJens Wiklander     unsigned char c;
652817466cbSJens Wiklander 
653817466cbSJens Wiklander     if( ( f = fopen( path, "rb" ) ) == NULL )
654817466cbSJens Wiklander         return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
655817466cbSJens Wiklander 
6563d3b0591SJens Wiklander     n = fread( buf, 1, sizeof( buf ), f );
6573d3b0591SJens Wiklander     if( fread( &c, 1, 1, f ) != 0 )
658817466cbSJens Wiklander     {
6593d3b0591SJens Wiklander         ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
6603d3b0591SJens Wiklander         goto exit;
661817466cbSJens Wiklander     }
6623d3b0591SJens Wiklander     if( n == 0 || ferror( f ) )
663817466cbSJens Wiklander     {
6643d3b0591SJens Wiklander         ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
6653d3b0591SJens Wiklander         goto exit;
666817466cbSJens Wiklander     }
667817466cbSJens Wiklander     fclose( f );
6683d3b0591SJens Wiklander     f = NULL;
669817466cbSJens Wiklander 
6703d3b0591SJens Wiklander     ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
671817466cbSJens Wiklander 
6723d3b0591SJens Wiklander exit:
6733d3b0591SJens Wiklander     mbedtls_platform_zeroize( buf, sizeof( buf ) );
6743d3b0591SJens Wiklander     if( f != NULL )
6753d3b0591SJens Wiklander         fclose( f );
6763d3b0591SJens Wiklander     if( ret != 0 )
6773d3b0591SJens Wiklander         return( ret );
678817466cbSJens Wiklander     return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
679817466cbSJens Wiklander }
680817466cbSJens Wiklander #endif /* MBEDTLS_FS_IO */
681817466cbSJens Wiklander 
682817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST)
683817466cbSJens Wiklander 
684817466cbSJens Wiklander static const unsigned char entropy_source_pr[96] =
685817466cbSJens Wiklander     { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
686817466cbSJens Wiklander       0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
687817466cbSJens Wiklander       0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
688817466cbSJens Wiklander       0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
689817466cbSJens Wiklander       0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
690817466cbSJens Wiklander       0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
691817466cbSJens Wiklander       0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
692817466cbSJens Wiklander       0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
693817466cbSJens Wiklander       0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
694817466cbSJens Wiklander       0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
695817466cbSJens Wiklander       0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
696817466cbSJens Wiklander       0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
697817466cbSJens Wiklander 
698817466cbSJens Wiklander static const unsigned char entropy_source_nopr[64] =
699817466cbSJens Wiklander     { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
700817466cbSJens Wiklander       0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
701817466cbSJens Wiklander       0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
702817466cbSJens Wiklander       0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
703817466cbSJens Wiklander       0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
704817466cbSJens Wiklander       0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
705817466cbSJens Wiklander       0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
706817466cbSJens Wiklander       0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
707817466cbSJens Wiklander 
708817466cbSJens Wiklander static const unsigned char nonce_pers_pr[16] =
709817466cbSJens Wiklander     { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
710817466cbSJens Wiklander       0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
711817466cbSJens Wiklander 
712817466cbSJens Wiklander static const unsigned char nonce_pers_nopr[16] =
713817466cbSJens Wiklander     { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
714817466cbSJens Wiklander       0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
715817466cbSJens Wiklander 
716*11fa71b9SJerome Forissier #if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
717*11fa71b9SJerome Forissier static const unsigned char result_pr[16] =
718*11fa71b9SJerome Forissier     { 0x95, 0x3c, 0xa5, 0xbd, 0x44, 0x1, 0x34, 0xb7,
719*11fa71b9SJerome Forissier       0x13, 0x58, 0x3e, 0x6a, 0x6c, 0x7e, 0x88, 0x8a };
720*11fa71b9SJerome Forissier 
721*11fa71b9SJerome Forissier static const unsigned char result_nopr[16] =
722*11fa71b9SJerome Forissier     { 0x6c, 0x25, 0x27, 0x95, 0xa3, 0x62, 0xd6, 0xdb,
723*11fa71b9SJerome Forissier       0x90, 0xfd, 0x69, 0xb5, 0x42, 0x9, 0x4b, 0x84 };
724*11fa71b9SJerome Forissier #else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
725817466cbSJens Wiklander static const unsigned char result_pr[16] =
726817466cbSJens Wiklander     { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
727817466cbSJens Wiklander       0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
728817466cbSJens Wiklander 
729817466cbSJens Wiklander static const unsigned char result_nopr[16] =
730817466cbSJens Wiklander     { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
731817466cbSJens Wiklander       0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
732*11fa71b9SJerome Forissier #endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
733817466cbSJens Wiklander 
734817466cbSJens Wiklander static size_t test_offset;
735817466cbSJens Wiklander static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
736817466cbSJens Wiklander                                        size_t len )
737817466cbSJens Wiklander {
738817466cbSJens Wiklander     const unsigned char *p = data;
739817466cbSJens Wiklander     memcpy( buf, p + test_offset, len );
740817466cbSJens Wiklander     test_offset += len;
741817466cbSJens Wiklander     return( 0 );
742817466cbSJens Wiklander }
743817466cbSJens Wiklander 
744817466cbSJens Wiklander #define CHK( c )    if( (c) != 0 )                          \
745817466cbSJens Wiklander                     {                                       \
746817466cbSJens Wiklander                         if( verbose != 0 )                  \
747817466cbSJens Wiklander                             mbedtls_printf( "failed\n" );  \
748817466cbSJens Wiklander                         return( 1 );                        \
749817466cbSJens Wiklander                     }
750817466cbSJens Wiklander 
751817466cbSJens Wiklander /*
752817466cbSJens Wiklander  * Checkup routine
753817466cbSJens Wiklander  */
754817466cbSJens Wiklander int mbedtls_ctr_drbg_self_test( int verbose )
755817466cbSJens Wiklander {
756817466cbSJens Wiklander     mbedtls_ctr_drbg_context ctx;
757817466cbSJens Wiklander     unsigned char buf[16];
758817466cbSJens Wiklander 
759817466cbSJens Wiklander     mbedtls_ctr_drbg_init( &ctx );
760817466cbSJens Wiklander 
761817466cbSJens Wiklander     /*
762817466cbSJens Wiklander      * Based on a NIST CTR_DRBG test vector (PR = True)
763817466cbSJens Wiklander      */
764817466cbSJens Wiklander     if( verbose != 0 )
765817466cbSJens Wiklander         mbedtls_printf( "  CTR_DRBG (PR = TRUE) : " );
766817466cbSJens Wiklander 
767817466cbSJens Wiklander     test_offset = 0;
7685b25c76aSJerome Forissier     mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
769*11fa71b9SJerome Forissier     mbedtls_ctr_drbg_set_nonce_len( &ctx, 0 );
7705b25c76aSJerome Forissier     CHK( mbedtls_ctr_drbg_seed( &ctx,
7715b25c76aSJerome Forissier                                 ctr_drbg_self_test_entropy,
7725b25c76aSJerome Forissier                                 (void *) entropy_source_pr,
7735b25c76aSJerome Forissier                                 nonce_pers_pr, 16 ) );
774817466cbSJens Wiklander     mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
775817466cbSJens Wiklander     CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
776817466cbSJens Wiklander     CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
777817466cbSJens Wiklander     CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
778817466cbSJens Wiklander 
779817466cbSJens Wiklander     mbedtls_ctr_drbg_free( &ctx );
780817466cbSJens Wiklander 
781817466cbSJens Wiklander     if( verbose != 0 )
782817466cbSJens Wiklander         mbedtls_printf( "passed\n" );
783817466cbSJens Wiklander 
784817466cbSJens Wiklander     /*
785817466cbSJens Wiklander      * Based on a NIST CTR_DRBG test vector (PR = FALSE)
786817466cbSJens Wiklander      */
787817466cbSJens Wiklander     if( verbose != 0 )
788817466cbSJens Wiklander         mbedtls_printf( "  CTR_DRBG (PR = FALSE): " );
789817466cbSJens Wiklander 
790817466cbSJens Wiklander     mbedtls_ctr_drbg_init( &ctx );
791817466cbSJens Wiklander 
792817466cbSJens Wiklander     test_offset = 0;
7935b25c76aSJerome Forissier     mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
794*11fa71b9SJerome Forissier     mbedtls_ctr_drbg_set_nonce_len( &ctx, 0 );
7955b25c76aSJerome Forissier     CHK( mbedtls_ctr_drbg_seed( &ctx,
7965b25c76aSJerome Forissier                                 ctr_drbg_self_test_entropy,
7975b25c76aSJerome Forissier                                 (void *) entropy_source_nopr,
7985b25c76aSJerome Forissier                                 nonce_pers_nopr, 16 ) );
799817466cbSJens Wiklander     CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
800817466cbSJens Wiklander     CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
801817466cbSJens Wiklander     CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
802817466cbSJens Wiklander     CHK( memcmp( buf, result_nopr, 16 ) );
803817466cbSJens Wiklander 
804817466cbSJens Wiklander     mbedtls_ctr_drbg_free( &ctx );
805817466cbSJens Wiklander 
806817466cbSJens Wiklander     if( verbose != 0 )
807817466cbSJens Wiklander         mbedtls_printf( "passed\n" );
808817466cbSJens Wiklander 
809817466cbSJens Wiklander     if( verbose != 0 )
810817466cbSJens Wiklander             mbedtls_printf( "\n" );
811817466cbSJens Wiklander 
812817466cbSJens Wiklander     return( 0 );
813817466cbSJens Wiklander }
814817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST */
815817466cbSJens Wiklander 
816817466cbSJens Wiklander #endif /* MBEDTLS_CTR_DRBG_C */
817