blob: ed31576a7b8d9649721b8f26fb990732f07343c8 [file] [log] [blame]
Paul Bakker0e04d0e2011-11-27 14:46:59 +00001/*
2 * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakker0e04d0e2011-11-27 14:46:59 +000018 */
19/*
Paul Sokolovsky8d6d8c82018-02-10 11:11:41 +020020 * The NIST SP 800-90 DRBGs are described in the following publication.
Paul Bakker0e04d0e2011-11-27 14:46:59 +000021 *
22 * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
23 */
24
Gilles Peskinedb09ef62020-06-03 01:43:33 +020025#include "common.h"
Paul Bakker0e04d0e2011-11-27 14:46:59 +000026
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020027#if defined(MBEDTLS_CTR_DRBG_C)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000028
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000029#include "mbedtls/ctr_drbg.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050030#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000031#include "mbedtls/error.h"
Paul Bakker0e04d0e2011-11-27 14:46:59 +000032
Rich Evans00ab4702015-02-06 13:43:58 +000033#include <string.h>
34
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020035#if defined(MBEDTLS_FS_IO)
Paul Bakkerfc754a92011-12-05 13:23:51 +000036#include <stdio.h>
37#endif
38
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000039#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010040
Paul Bakker18d32912011-12-10 21:42:49 +000041/*
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020042 * CTR_DRBG context initialization
43 */
44void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
45{
46 memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
Gilles Peskinee9a34542019-10-22 20:43:24 +020047 /* Indicate that the entropy nonce length is not set explicitly.
48 * See mbedtls_ctr_drbg_set_nonce_len(). */
49 ctx->reseed_counter = -1;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010050
Gavin Acquroff6aceb512020-03-01 17:06:11 -080051 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020052}
53
Gavin Acquroff6aceb512020-03-01 17:06:11 -080054/*
55 * This function resets CTR_DRBG context to the state immediately
56 * after initial call of mbedtls_ctr_drbg_init().
57 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020058void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
Paul Bakkerfff03662014-06-18 16:21:25 +020059{
60 if( ctx == NULL )
61 return;
62
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010063#if defined(MBEDTLS_THREADING_C)
Gilles Peskineda290f92021-02-09 18:44:02 +010064 /* The mutex is initialized iff f_entropy is set. */
Gilles Peskinef4b34292021-01-30 13:05:32 +010065 if( ctx->f_entropy != NULL )
66 mbedtls_mutex_free( &ctx->mutex );
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010067#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020068 mbedtls_aes_free( &ctx->aes_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050069 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Gavin Acquroff6aceb512020-03-01 17:06:11 -080070 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
71 ctx->reseed_counter = -1;
Paul Bakkerfff03662014-06-18 16:21:25 +020072}
73
Hanno Beckera08651f2018-10-05 09:38:59 +010074void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx,
75 int resistance )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000076{
77 ctx->prediction_resistance = resistance;
78}
79
Hanno Beckera08651f2018-10-05 09:38:59 +010080void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx,
81 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000082{
83 ctx->entropy_len = len;
84}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +020085
Gilles Peskine9be50982019-10-22 18:42:27 +020086int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx,
87 size_t len )
88{
89 /* If mbedtls_ctr_drbg_seed() has already been called, it's
90 * too late. Return the error code that's closest to making sense. */
91 if( ctx->f_entropy != NULL )
92 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
93
94 if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
95 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
96#if SIZE_MAX > INT_MAX
97 /* This shouldn't be an issue because
98 * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible
99 * configuration, but make sure anyway. */
100 if( len > INT_MAX )
101 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
102#endif
103
104 /* For backward compatibility with Mbed TLS <= 2.19, store the
105 * entropy nonce length in a field that already exists, but isn't
106 * used until after the initial seeding. */
107 /* Due to the capping of len above, the value fits in an int. */
108 ctx->reseed_counter = (int) len;
109 return( 0 );
110}
111
Hanno Beckera08651f2018-10-05 09:38:59 +0100112void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx,
113 int interval )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000114{
115 ctx->reseed_interval = interval;
116}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200117
118static int block_cipher_df( unsigned char *output,
119 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000120{
Hanno Beckera08651f2018-10-05 09:38:59 +0100121 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
122 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200123 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
124 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
125 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100126 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200127 mbedtls_aes_context aes_ctx;
Dvir Markovich1b364992017-06-26 13:43:34 +0300128 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000129
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200130 int i, j;
131 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000132
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200133 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
134 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100135
Hanno Beckera08651f2018-10-05 09:38:59 +0100136 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
137 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200138 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000139
140 /*
141 * Construct IV (16 bytes) and S in buffer
142 * IV = Counter (in 32-bits) padded to 16 with zeroes
143 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
144 * data || 0x80
145 * (Total is padded to a multiple of 16-bytes with zeroes)
146 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200147 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Joe Subbiania651e6f2021-08-23 11:35:25 +0100148 MBEDTLS_PUT_UINT32_BE( data_len, p, 0);
149 p += 4 + 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200150 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000151 memcpy( p, data, data_len );
152 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000153
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200154 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000155
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200156 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000157 key[i] = i;
158
Hanno Beckera08651f2018-10-05 09:38:59 +0100159 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key,
160 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300161 {
162 goto exit;
163 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000164
165 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200166 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000167 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200168 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000169 {
170 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200171 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000172 use_len = buf_len;
173
174 while( use_len > 0 )
175 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200176 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000177 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200178 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
179 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
180 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000181
Hanno Beckera08651f2018-10-05 09:38:59 +0100182 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
183 chain, chain ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300184 {
185 goto exit;
186 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000187 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200188
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200189 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000190
191 /*
192 * Update IV
193 */
194 buf[3]++;
195 }
196
197 /*
198 * Do final encryption with reduced data
199 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100200 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp,
201 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300202 {
203 goto exit;
204 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200205 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000206 p = output;
207
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200208 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000209 {
Hanno Beckera08651f2018-10-05 09:38:59 +0100210 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
211 iv, iv ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300212 {
213 goto exit;
214 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200215 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
216 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000217 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300218exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200219 mbedtls_aes_free( &aes_ctx );
Dvir Markovich1b364992017-06-26 13:43:34 +0300220 /*
221 * tidy up the stack
222 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500223 mbedtls_platform_zeroize( buf, sizeof( buf ) );
224 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
225 mbedtls_platform_zeroize( key, sizeof( key ) );
226 mbedtls_platform_zeroize( chain, sizeof( chain ) );
Dvir Markovich1b364992017-06-26 13:43:34 +0300227 if( 0 != ret )
228 {
229 /*
230 * wipe partial seed from memory
231 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500232 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
Dvir Markovich1b364992017-06-26 13:43:34 +0300233 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200234
Dvir Markovich1b364992017-06-26 13:43:34 +0300235 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000236}
237
Gilles Peskineed7da592018-08-03 20:16:52 +0200238/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
239 * ctr_drbg_update_internal(ctx, provided_data)
240 * implements
241 * CTR_DRBG_Update(provided_data, Key, V)
242 * with inputs and outputs
243 * ctx->aes_ctx = Key
244 * ctx->counter = V
245 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200246static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
Hanno Beckera08651f2018-10-05 09:38:59 +0100247 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000248{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200249 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000250 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000251 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300252 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000253
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200254 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000255
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200256 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000257 {
258 /*
259 * Increase counter
260 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200261 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000262 if( ++ctx->counter[i - 1] != 0 )
263 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000264
265 /*
266 * Crypt counter block
267 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100268 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
269 ctx->counter, p ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300270 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200271 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300272 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000273
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200274 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000275 }
276
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200277 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000278 tmp[i] ^= data[i];
279
280 /*
281 * Update key and counter
282 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100283 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp,
284 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300285 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200286 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300287 }
Hanno Beckera08651f2018-10-05 09:38:59 +0100288 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
289 MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000290
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200291exit:
292 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
293 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000294}
295
Gilles Peskineed7da592018-08-03 20:16:52 +0200296/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
297 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
298 * implements
299 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
300 * security_strength) -> initial_working_state
301 * with inputs
302 * ctx->counter = all-bits-0
303 * ctx->aes_ctx = context from all-bits-0 key
304 * additional[:add_len] = entropy_input || nonce || personalization_string
305 * and with outputs
306 * ctx = initial_working_state
307 */
Gilles Peskined9199932018-09-11 16:41:54 +0200308int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
309 const unsigned char *additional,
310 size_t add_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000311{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200312 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Janos Follath24eed8d2019-11-22 13:21:35 +0000313 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000314
Gilles Peskined9199932018-09-11 16:41:54 +0200315 if( add_len == 0 )
316 return( 0 );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100317
Gilles Peskined9199932018-09-11 16:41:54 +0200318 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
319 goto exit;
320 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
321 goto exit;
322
323exit:
324 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
325 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000326}
327
Gilles Peskined9199932018-09-11 16:41:54 +0200328#if !defined(MBEDTLS_DEPRECATED_REMOVED)
329void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
330 const unsigned char *additional,
331 size_t add_len )
332{
333 /* MAX_INPUT would be more logical here, but we have to match
334 * block_cipher_df()'s limits since we can't propagate errors */
335 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
336 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
337 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
338}
339#endif /* MBEDTLS_DEPRECATED_REMOVED */
340
Gilles Peskineed7da592018-08-03 20:16:52 +0200341/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
Gilles Peskine9be50982019-10-22 18:42:27 +0200342 * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
Gilles Peskineed7da592018-08-03 20:16:52 +0200343 * implements
344 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
345 * -> new_working_state
346 * with inputs
347 * ctx contains working_state
348 * additional[:len] = additional_input
349 * and entropy_input comes from calling ctx->f_entropy
Gilles Peskine9be50982019-10-22 18:42:27 +0200350 * for (ctx->entropy_len + nonce_len) bytes
Gilles Peskineed7da592018-08-03 20:16:52 +0200351 * and with output
352 * ctx contains new_working_state
353 */
Gilles Peskine97f59ab2019-10-22 18:42:27 +0200354static int mbedtls_ctr_drbg_reseed_internal( mbedtls_ctr_drbg_context *ctx,
355 const unsigned char *additional,
356 size_t len,
357 size_t nonce_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000358{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200359 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000360 size_t seedlen = 0;
Janos Follath24eed8d2019-11-22 13:21:35 +0000361 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000362
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200363 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
364 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Gilles Peskine9be50982019-10-22 18:42:27 +0200365 if( nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
366 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
367 if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200368 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000369
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200370 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000371
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200372 /* Gather entropy_len bytes of entropy to seed state. */
373 if( 0 != ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000374 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200375 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000376 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000377 seedlen += ctx->entropy_len;
378
Gilles Peskine9be50982019-10-22 18:42:27 +0200379 /* Gather entropy for a nonce if requested. */
380 if( nonce_len != 0 )
381 {
ENT\stroej14b919862020-12-23 17:28:33 -0600382 if( 0 != ctx->f_entropy( ctx->p_entropy, seed + seedlen, nonce_len ) )
Gilles Peskine9be50982019-10-22 18:42:27 +0200383 {
384 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
385 }
386 seedlen += nonce_len;
387 }
388
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200389 /* Add additional data if provided. */
390 if( additional != NULL && len != 0 )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000391 {
392 memcpy( seed + seedlen, additional, len );
393 seedlen += len;
394 }
395
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200396 /* Reduce to 384 bits. */
Dvir Markovich1b364992017-06-26 13:43:34 +0300397 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200398 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000399
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200400 /* Update state. */
Dvir Markovich1b364992017-06-26 13:43:34 +0300401 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200402 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000403 ctx->reseed_counter = 1;
404
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200405exit:
406 mbedtls_platform_zeroize( seed, sizeof( seed ) );
407 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000408}
Paul Bakker9af723c2014-05-01 13:03:14 +0200409
Gilles Peskine9be50982019-10-22 18:42:27 +0200410int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
411 const unsigned char *additional, size_t len )
412{
413 return( mbedtls_ctr_drbg_reseed_internal( ctx, additional, len, 0 ) );
414}
415
Gilles Peskinee9a34542019-10-22 20:43:24 +0200416/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
417 * is sufficient to achieve the maximum security strength given the key
418 * size and entropy length. If there is enough entropy in the initial
419 * call to the entropy function to serve as both the entropy input and
420 * the nonce, don't make a second call to get a nonce. */
421static size_t good_nonce_len( size_t entropy_len )
422{
423 if( entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 )
424 return( 0 );
425 else
426 return( ( entropy_len + 1 ) / 2 );
427}
428
Gilles Peskine8bf56132019-10-02 20:31:54 +0200429/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
Gilles Peskine379561f2019-10-18 16:57:48 +0200430 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
Gilles Peskine8bf56132019-10-02 20:31:54 +0200431 * implements
432 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
433 * security_strength) -> initial_working_state
434 * with inputs
435 * custom[:len] = nonce || personalization_string
Gilles Peskine379561f2019-10-18 16:57:48 +0200436 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
Gilles Peskine8bf56132019-10-02 20:31:54 +0200437 * and with outputs
438 * ctx = initial_working_state
439 */
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200440int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
441 int (*f_entropy)(void *, unsigned char *, size_t),
442 void *p_entropy,
443 const unsigned char *custom,
444 size_t len )
Gilles Peskine8bf56132019-10-02 20:31:54 +0200445{
Janos Follath24eed8d2019-11-22 13:21:35 +0000446 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200447 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Gilles Peskinee9a34542019-10-22 20:43:24 +0200448 size_t nonce_len;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200449
450 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
451
Gilles Peskineda290f92021-02-09 18:44:02 +0100452 /* The mutex is initialized iff f_entropy is set. */
Gilles Peskinef4b34292021-01-30 13:05:32 +0100453#if defined(MBEDTLS_THREADING_C)
454 mbedtls_mutex_init( &ctx->mutex );
455#endif
456
Gilles Peskine8bf56132019-10-02 20:31:54 +0200457 mbedtls_aes_init( &ctx->aes_ctx );
458
459 ctx->f_entropy = f_entropy;
460 ctx->p_entropy = p_entropy;
461
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200462 if( ctx->entropy_len == 0 )
463 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskinee9a34542019-10-22 20:43:24 +0200464 /* ctx->reseed_counter contains the desired amount of entropy to
465 * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
466 * If it's -1, indicating that the entropy nonce length was not set
467 * explicitly, use a sufficiently large nonce for security. */
468 nonce_len = ( ctx->reseed_counter >= 0 ?
469 (size_t) ctx->reseed_counter :
470 good_nonce_len( ctx->entropy_len ) );
471
Gilles Peskine9be50982019-10-22 18:42:27 +0200472 /* Initialize with an empty key. */
Gilles Peskine8bf56132019-10-02 20:31:54 +0200473 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
474 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
475 {
476 return( ret );
477 }
478
Gilles Peskinee9a34542019-10-22 20:43:24 +0200479 /* Do the initial seeding. */
Gilles Peskine9be50982019-10-22 18:42:27 +0200480 if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len,
Gilles Peskinee9a34542019-10-22 20:43:24 +0200481 nonce_len ) ) != 0 )
Gilles Peskine8bf56132019-10-02 20:31:54 +0200482 {
483 return( ret );
484 }
485 return( 0 );
486}
487
Gilles Peskineed7da592018-08-03 20:16:52 +0200488/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
489 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
490 * implements
491 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
492 * -> working_state_after_reseed
493 * if required, then
494 * CTR_DRBG_Generate(working_state_after_reseed,
495 * requested_number_of_bits, additional_input)
496 * -> status, returned_bits, new_working_state
497 * with inputs
498 * ctx contains working_state
499 * requested_number_of_bits = 8 * output_len
500 * additional[:add_len] = additional_input
501 * and entropy_input comes from calling ctx->f_entropy
502 * and with outputs
503 * status = SUCCESS (this function does the reseed internally)
504 * returned_bits = output[:output_len]
505 * ctx contains new_working_state
506 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200507int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000508 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000509 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000510{
511 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200512 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
513 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000514 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200515 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000516 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000517 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000518
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200519 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
520 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000521
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200522 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
523 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000524
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200525 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000526
527 if( ctx->reseed_counter > ctx->reseed_interval ||
528 ctx->prediction_resistance )
529 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200530 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300531 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000532 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300533 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000534 add_len = 0;
535 }
536
537 if( add_len > 0 )
538 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300539 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200540 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300541 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200542 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000543 }
544
545 while( output_len > 0 )
546 {
547 /*
548 * Increase counter
549 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200550 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000551 if( ++ctx->counter[i - 1] != 0 )
552 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000553
554 /*
555 * Crypt counter block
556 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100557 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
558 ctx->counter, tmp ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300559 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200560 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300561 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000562
Hanno Beckera08651f2018-10-05 09:38:59 +0100563 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE )
564 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000565 /*
566 * Copy random block to destination
567 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000568 memcpy( p, tmp, use_len );
569 p += use_len;
570 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000571 }
572
Dvir Markovich1b364992017-06-26 13:43:34 +0300573 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200574 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000575
576 ctx->reseed_counter++;
577
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200578exit:
579 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
580 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
Gilles Peskineafaee1c2019-11-28 09:45:32 +0100581 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000582}
583
Hanno Beckera08651f2018-10-05 09:38:59 +0100584int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output,
585 size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000586{
Janos Follath24eed8d2019-11-22 13:21:35 +0000587 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100588 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
589
590#if defined(MBEDTLS_THREADING_C)
591 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
592 return( ret );
593#endif
594
595 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
596
597#if defined(MBEDTLS_THREADING_C)
598 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
599 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
600#endif
601
602 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000603}
604
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200605#if defined(MBEDTLS_FS_IO)
Hanno Beckera08651f2018-10-05 09:38:59 +0100606int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx,
607 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000608{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200609 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000610 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200611 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000612
613 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200614 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000615
Hanno Beckera08651f2018-10-05 09:38:59 +0100616 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf,
617 MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200618 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000619
Hanno Beckera08651f2018-10-05 09:38:59 +0100620 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) !=
621 MBEDTLS_CTR_DRBG_MAX_INPUT )
622 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200623 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Hanno Beckera08651f2018-10-05 09:38:59 +0100624 }
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100625 else
Hanno Beckera08651f2018-10-05 09:38:59 +0100626 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100627 ret = 0;
Hanno Beckera08651f2018-10-05 09:38:59 +0100628 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000629
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100630exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500631 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200632
Paul Bakkerfc754a92011-12-05 13:23:51 +0000633 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200634 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000635}
636
Hanno Beckera08651f2018-10-05 09:38:59 +0100637int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx,
638 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000639{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100640 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200641 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000642 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200643 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200644 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000645
646 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200647 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000648
Gilles Peskine82204662018-09-11 18:43:09 +0200649 n = fread( buf, 1, sizeof( buf ), f );
650 if( fread( &c, 1, 1, f ) != 0 )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100651 {
Gilles Peskine82204662018-09-11 18:43:09 +0200652 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
653 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100654 }
Gilles Peskine82204662018-09-11 18:43:09 +0200655 if( n == 0 || ferror( f ) )
656 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100657 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200658 goto exit;
659 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000660 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200661 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200662
Gilles Peskine82204662018-09-11 18:43:09 +0200663 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
664
665exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500666 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200667 if( f != NULL )
668 fclose( f );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100669 if( ret != 0 )
670 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200671 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000672}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200673#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000674
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200675#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000676
ENT\stroej170f63d02020-12-28 08:50:23 -0600677/* The CTR_DRBG NIST test vectors used here are available at
678 * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip
679 *
680 * The parameters used to derive the test data are:
681 *
682 * [AES-128 use df]
683 * [PredictionResistance = True/False]
684 * [EntropyInputLen = 128]
685 * [NonceLen = 64]
686 * [PersonalizationStringLen = 128]
687 * [AdditionalInputLen = 0]
688 * [ReturnedBitsLen = 512]
689 *
690 * [AES-256 use df]
691 * [PredictionResistance = True/False]
692 * [EntropyInputLen = 256]
693 * [NonceLen = 128]
694 * [PersonalizationStringLen = 256]
695 * [AdditionalInputLen = 0]
696 * [ReturnedBitsLen = 512]
697 *
698 */
699
Gilles Peskine02e79a42019-10-07 17:06:06 +0200700#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
ENT\stroej1df307002020-12-26 12:41:04 -0600701static const unsigned char entropy_source_pr[] =
702 { 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb,
703 0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92,
704 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8,
705 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20,
706 0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0,
707 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad,
708 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200709
ENT\stroej1df307002020-12-26 12:41:04 -0600710static const unsigned char entropy_source_nopr[] =
711 { 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45,
712 0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9,
713 0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20,
714 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f,
715 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c };
716
stroebeljcd4de1b52021-01-04 18:14:32 -0600717static const unsigned char pers_pr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600718 { 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a,
719 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad };
720
stroebeljcd4de1b52021-01-04 18:14:32 -0600721static const unsigned char pers_nopr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600722 { 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c,
723 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f };
724
725static const unsigned char result_pr[] =
726 { 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66,
727 0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff,
728 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10,
729 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30,
730 0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4,
731 0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc,
732 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06,
733 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf };
734
735static const unsigned char result_nopr[] =
736 { 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13,
737 0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0,
738 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf,
739 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2,
740 0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7,
741 0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2,
742 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02,
743 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200744#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000745
ENT\stroej1df307002020-12-26 12:41:04 -0600746static const unsigned char entropy_source_pr[] =
747 { 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49,
748 0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a,
749 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85,
750 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e,
751 0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15,
752 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45,
753 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8,
754 0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c,
755 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3,
756 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce,
757 0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e,
758 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76,
759 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77,
760 0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe };
761
762static const unsigned char entropy_source_nopr[] =
763 { 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d,
764 0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0,
765 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73,
766 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c,
767 0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2,
768 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1,
769 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a,
770 0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb,
771 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a,
772 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 };
773
stroebeljcd4de1b52021-01-04 18:14:32 -0600774static const unsigned char pers_pr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600775 { 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33,
776 0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e,
777 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0,
778 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 };
779
stroebeljcd4de1b52021-01-04 18:14:32 -0600780static const unsigned char pers_nopr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600781 { 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29,
782 0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf,
783 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb,
784 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b };
785
786static const unsigned char result_pr[] =
787 { 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85,
788 0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d,
789 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62,
790 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d,
791 0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb,
792 0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39,
793 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40,
794 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 };
795
796static const unsigned char result_nopr[] =
797 { 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad,
798 0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3,
799 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b,
800 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14,
801 0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54,
802 0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30,
803 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a,
804 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200805#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000806
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100807static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200808static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
809 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000810{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100811 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000812 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100813 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000814 return( 0 );
815}
816
Paul Bakker7dc4c442014-02-01 22:50:26 +0100817#define CHK( c ) if( (c) != 0 ) \
818 { \
819 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200820 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100821 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100822 }
823
bootstrap-prime7ef96ea2022-05-18 14:08:33 -0400824#define SELF_TEST_OUTPUT_DISCARD_LENGTH 64
stroebeljcd4de1b52021-01-04 18:14:32 -0600825
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000826/*
827 * Checkup routine
828 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200829int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000830{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200831 mbedtls_ctr_drbg_context ctx;
stroebeljcd4de1b52021-01-04 18:14:32 -0600832 unsigned char buf[ sizeof( result_pr ) ];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000833
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200834 mbedtls_ctr_drbg_init( &ctx );
835
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000836 /*
837 * Based on a NIST CTR_DRBG test vector (PR = True)
838 */
839 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200840 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000841
842 test_offset = 0;
ENT\stroej1df307002020-12-26 12:41:04 -0600843 mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE );
stroebeljcd4de1b52021-01-04 18:14:32 -0600844 mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200845 CHK( mbedtls_ctr_drbg_seed( &ctx,
846 ctr_drbg_self_test_entropy,
847 (void *) entropy_source_pr,
stroebeljcd4de1b52021-01-04 18:14:32 -0600848 pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200849 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
bootstrap-prime7ef96ea2022-05-18 14:08:33 -0400850 CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH ) );
stroebeljcd4de1b52021-01-04 18:14:32 -0600851 CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_pr ) ) );
852 CHK( memcmp( buf, result_pr, sizeof( result_pr ) ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000853
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100854 mbedtls_ctr_drbg_free( &ctx );
855
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000856 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200857 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000858
859 /*
860 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
861 */
862 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200863 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000864
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100865 mbedtls_ctr_drbg_init( &ctx );
866
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000867 test_offset = 0;
ENT\stroej1df307002020-12-26 12:41:04 -0600868 mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
stroebeljcd4de1b52021-01-04 18:14:32 -0600869 mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200870 CHK( mbedtls_ctr_drbg_seed( &ctx,
871 ctr_drbg_self_test_entropy,
872 (void *) entropy_source_nopr,
stroebeljcd4de1b52021-01-04 18:14:32 -0600873 pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200874 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
bootstrap-prime7ef96ea2022-05-18 14:08:33 -0400875 CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH ) );
stroebeljcd4de1b52021-01-04 18:14:32 -0600876 CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_nopr ) ) );
877 CHK( memcmp( buf, result_nopr, sizeof( result_nopr ) ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000878
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100879 mbedtls_ctr_drbg_free( &ctx );
880
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000881 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200882 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000883
884 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200885 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000886
887 return( 0 );
888}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200889#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000890
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200891#endif /* MBEDTLS_CTR_DRBG_C */