blob: 48efada97078c26d5f38b367169a7c567d9db87b [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é-Gonnard2cf5a7c2015-04-08 12:49:31 +020039#if defined(MBEDTLS_SELF_TEST)
40#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000041#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010042#else
Rich Evans00ab4702015-02-06 13:43:58 +000043#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#define mbedtls_printf printf
45#endif /* MBEDTLS_PLATFORM_C */
46#endif /* MBEDTLS_SELF_TEST */
Paul Bakker7dc4c442014-02-01 22:50:26 +010047
Paul Bakker18d32912011-12-10 21:42:49 +000048/*
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020049 * CTR_DRBG context initialization
50 */
51void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
52{
53 memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
Gilles Peskinee9a34542019-10-22 20:43:24 +020054 /* Indicate that the entropy nonce length is not set explicitly.
55 * See mbedtls_ctr_drbg_set_nonce_len(). */
56 ctx->reseed_counter = -1;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010057
Gavin Acquroff6aceb512020-03-01 17:06:11 -080058 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020059}
60
Gavin Acquroff6aceb512020-03-01 17:06:11 -080061/*
62 * This function resets CTR_DRBG context to the state immediately
63 * after initial call of mbedtls_ctr_drbg_init().
64 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020065void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
Paul Bakkerfff03662014-06-18 16:21:25 +020066{
67 if( ctx == NULL )
68 return;
69
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010070#if defined(MBEDTLS_THREADING_C)
Gilles Peskinef4b34292021-01-30 13:05:32 +010071 if( ctx->f_entropy != NULL )
72 mbedtls_mutex_free( &ctx->mutex );
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010073#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020074 mbedtls_aes_free( &ctx->aes_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050075 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Gavin Acquroff6aceb512020-03-01 17:06:11 -080076 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
77 ctx->reseed_counter = -1;
Paul Bakkerfff03662014-06-18 16:21:25 +020078}
79
Hanno Beckera08651f2018-10-05 09:38:59 +010080void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx,
81 int resistance )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000082{
83 ctx->prediction_resistance = resistance;
84}
85
Hanno Beckera08651f2018-10-05 09:38:59 +010086void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx,
87 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000088{
89 ctx->entropy_len = len;
90}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +020091
Gilles Peskine9be50982019-10-22 18:42:27 +020092int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx,
93 size_t len )
94{
95 /* If mbedtls_ctr_drbg_seed() has already been called, it's
96 * too late. Return the error code that's closest to making sense. */
97 if( ctx->f_entropy != NULL )
98 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
99
100 if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
101 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
102#if SIZE_MAX > INT_MAX
103 /* This shouldn't be an issue because
104 * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible
105 * configuration, but make sure anyway. */
106 if( len > INT_MAX )
107 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
108#endif
109
110 /* For backward compatibility with Mbed TLS <= 2.19, store the
111 * entropy nonce length in a field that already exists, but isn't
112 * used until after the initial seeding. */
113 /* Due to the capping of len above, the value fits in an int. */
114 ctx->reseed_counter = (int) len;
115 return( 0 );
116}
117
Hanno Beckera08651f2018-10-05 09:38:59 +0100118void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx,
119 int interval )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000120{
121 ctx->reseed_interval = interval;
122}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200123
124static int block_cipher_df( unsigned char *output,
125 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000126{
Hanno Beckera08651f2018-10-05 09:38:59 +0100127 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
128 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200129 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
130 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
131 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100132 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200133 mbedtls_aes_context aes_ctx;
Dvir Markovich1b364992017-06-26 13:43:34 +0300134 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000135
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200136 int i, j;
137 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000138
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200139 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
140 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100141
Hanno Beckera08651f2018-10-05 09:38:59 +0100142 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
143 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200144 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000145
146 /*
147 * Construct IV (16 bytes) and S in buffer
148 * IV = Counter (in 32-bits) padded to 16 with zeroes
149 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
150 * data || 0x80
151 * (Total is padded to a multiple of 16-bytes with zeroes)
152 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200153 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000154 *p++ = ( data_len >> 24 ) & 0xff;
155 *p++ = ( data_len >> 16 ) & 0xff;
156 *p++ = ( data_len >> 8 ) & 0xff;
157 *p++ = ( data_len ) & 0xff;
158 p += 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200159 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000160 memcpy( p, data, data_len );
161 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000162
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200163 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000164
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200165 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000166 key[i] = i;
167
Hanno Beckera08651f2018-10-05 09:38:59 +0100168 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key,
169 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300170 {
171 goto exit;
172 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000173
174 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200175 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000176 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200177 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000178 {
179 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200180 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000181 use_len = buf_len;
182
183 while( use_len > 0 )
184 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200185 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000186 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200187 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
188 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
189 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000190
Hanno Beckera08651f2018-10-05 09:38:59 +0100191 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
192 chain, chain ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300193 {
194 goto exit;
195 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000196 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200197
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200198 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000199
200 /*
201 * Update IV
202 */
203 buf[3]++;
204 }
205
206 /*
207 * Do final encryption with reduced data
208 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100209 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp,
210 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300211 {
212 goto exit;
213 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200214 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000215 p = output;
216
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200217 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000218 {
Hanno Beckera08651f2018-10-05 09:38:59 +0100219 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
220 iv, iv ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300221 {
222 goto exit;
223 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200224 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
225 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000226 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300227exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200228 mbedtls_aes_free( &aes_ctx );
Dvir Markovich1b364992017-06-26 13:43:34 +0300229 /*
230 * tidy up the stack
231 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500232 mbedtls_platform_zeroize( buf, sizeof( buf ) );
233 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
234 mbedtls_platform_zeroize( key, sizeof( key ) );
235 mbedtls_platform_zeroize( chain, sizeof( chain ) );
Dvir Markovich1b364992017-06-26 13:43:34 +0300236 if( 0 != ret )
237 {
238 /*
239 * wipe partial seed from memory
240 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500241 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
Dvir Markovich1b364992017-06-26 13:43:34 +0300242 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200243
Dvir Markovich1b364992017-06-26 13:43:34 +0300244 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000245}
246
Gilles Peskineed7da592018-08-03 20:16:52 +0200247/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
248 * ctr_drbg_update_internal(ctx, provided_data)
249 * implements
250 * CTR_DRBG_Update(provided_data, Key, V)
251 * with inputs and outputs
252 * ctx->aes_ctx = Key
253 * ctx->counter = V
254 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200255static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
Hanno Beckera08651f2018-10-05 09:38:59 +0100256 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000257{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200258 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000259 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000260 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300261 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000262
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200263 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000264
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200265 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000266 {
267 /*
268 * Increase counter
269 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200270 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000271 if( ++ctx->counter[i - 1] != 0 )
272 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000273
274 /*
275 * Crypt counter block
276 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100277 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
278 ctx->counter, p ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300279 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200280 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300281 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000282
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200283 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000284 }
285
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200286 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000287 tmp[i] ^= data[i];
288
289 /*
290 * Update key and counter
291 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100292 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp,
293 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300294 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200295 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300296 }
Hanno Beckera08651f2018-10-05 09:38:59 +0100297 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
298 MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000299
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200300exit:
301 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
302 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000303}
304
Gilles Peskineed7da592018-08-03 20:16:52 +0200305/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
306 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
307 * implements
308 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
309 * security_strength) -> initial_working_state
310 * with inputs
311 * ctx->counter = all-bits-0
312 * ctx->aes_ctx = context from all-bits-0 key
313 * additional[:add_len] = entropy_input || nonce || personalization_string
314 * and with outputs
315 * ctx = initial_working_state
316 */
Gilles Peskined9199932018-09-11 16:41:54 +0200317int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
318 const unsigned char *additional,
319 size_t add_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000320{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200321 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Janos Follath24eed8d2019-11-22 13:21:35 +0000322 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000323
Gilles Peskined9199932018-09-11 16:41:54 +0200324 if( add_len == 0 )
325 return( 0 );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100326
Gilles Peskined9199932018-09-11 16:41:54 +0200327 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
328 goto exit;
329 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
330 goto exit;
331
332exit:
333 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
334 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000335}
336
Gilles Peskined9199932018-09-11 16:41:54 +0200337#if !defined(MBEDTLS_DEPRECATED_REMOVED)
338void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
339 const unsigned char *additional,
340 size_t add_len )
341{
342 /* MAX_INPUT would be more logical here, but we have to match
343 * block_cipher_df()'s limits since we can't propagate errors */
344 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
345 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
346 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
347}
348#endif /* MBEDTLS_DEPRECATED_REMOVED */
349
Gilles Peskineed7da592018-08-03 20:16:52 +0200350/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
Gilles Peskine9be50982019-10-22 18:42:27 +0200351 * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
Gilles Peskineed7da592018-08-03 20:16:52 +0200352 * implements
353 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
354 * -> new_working_state
355 * with inputs
356 * ctx contains working_state
357 * additional[:len] = additional_input
358 * and entropy_input comes from calling ctx->f_entropy
Gilles Peskine9be50982019-10-22 18:42:27 +0200359 * for (ctx->entropy_len + nonce_len) bytes
Gilles Peskineed7da592018-08-03 20:16:52 +0200360 * and with output
361 * ctx contains new_working_state
362 */
Gilles Peskine97f59ab2019-10-22 18:42:27 +0200363static int mbedtls_ctr_drbg_reseed_internal( mbedtls_ctr_drbg_context *ctx,
364 const unsigned char *additional,
365 size_t len,
366 size_t nonce_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000367{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200368 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000369 size_t seedlen = 0;
Janos Follath24eed8d2019-11-22 13:21:35 +0000370 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000371
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200372 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
373 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Gilles Peskine9be50982019-10-22 18:42:27 +0200374 if( nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
375 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
376 if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200377 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000378
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200379 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000380
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200381 /* Gather entropy_len bytes of entropy to seed state. */
382 if( 0 != ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000383 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200384 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000385 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000386 seedlen += ctx->entropy_len;
387
Gilles Peskine9be50982019-10-22 18:42:27 +0200388 /* Gather entropy for a nonce if requested. */
389 if( nonce_len != 0 )
390 {
ENT\stroej14b919862020-12-23 17:28:33 -0600391 if( 0 != ctx->f_entropy( ctx->p_entropy, seed + seedlen, nonce_len ) )
Gilles Peskine9be50982019-10-22 18:42:27 +0200392 {
393 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
394 }
395 seedlen += nonce_len;
396 }
397
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200398 /* Add additional data if provided. */
399 if( additional != NULL && len != 0 )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000400 {
401 memcpy( seed + seedlen, additional, len );
402 seedlen += len;
403 }
404
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200405 /* Reduce to 384 bits. */
Dvir Markovich1b364992017-06-26 13:43:34 +0300406 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200407 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000408
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200409 /* Update state. */
Dvir Markovich1b364992017-06-26 13:43:34 +0300410 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200411 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000412 ctx->reseed_counter = 1;
413
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200414exit:
415 mbedtls_platform_zeroize( seed, sizeof( seed ) );
416 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000417}
Paul Bakker9af723c2014-05-01 13:03:14 +0200418
Gilles Peskine9be50982019-10-22 18:42:27 +0200419int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
420 const unsigned char *additional, size_t len )
421{
422 return( mbedtls_ctr_drbg_reseed_internal( ctx, additional, len, 0 ) );
423}
424
Gilles Peskinee9a34542019-10-22 20:43:24 +0200425/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
426 * is sufficient to achieve the maximum security strength given the key
427 * size and entropy length. If there is enough entropy in the initial
428 * call to the entropy function to serve as both the entropy input and
429 * the nonce, don't make a second call to get a nonce. */
430static size_t good_nonce_len( size_t entropy_len )
431{
432 if( entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 )
433 return( 0 );
434 else
435 return( ( entropy_len + 1 ) / 2 );
436}
437
Gilles Peskine8bf56132019-10-02 20:31:54 +0200438/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
Gilles Peskine379561f2019-10-18 16:57:48 +0200439 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
Gilles Peskine8bf56132019-10-02 20:31:54 +0200440 * implements
441 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
442 * security_strength) -> initial_working_state
443 * with inputs
444 * custom[:len] = nonce || personalization_string
Gilles Peskine379561f2019-10-18 16:57:48 +0200445 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
Gilles Peskine8bf56132019-10-02 20:31:54 +0200446 * and with outputs
447 * ctx = initial_working_state
448 */
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200449int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
450 int (*f_entropy)(void *, unsigned char *, size_t),
451 void *p_entropy,
452 const unsigned char *custom,
453 size_t len )
Gilles Peskine8bf56132019-10-02 20:31:54 +0200454{
Janos Follath24eed8d2019-11-22 13:21:35 +0000455 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200456 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Gilles Peskinee9a34542019-10-22 20:43:24 +0200457 size_t nonce_len;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200458
459 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
460
Gilles Peskinef4b34292021-01-30 13:05:32 +0100461#if defined(MBEDTLS_THREADING_C)
462 mbedtls_mutex_init( &ctx->mutex );
463#endif
464
Gilles Peskine8bf56132019-10-02 20:31:54 +0200465 mbedtls_aes_init( &ctx->aes_ctx );
466
467 ctx->f_entropy = f_entropy;
468 ctx->p_entropy = p_entropy;
469
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200470 if( ctx->entropy_len == 0 )
471 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskinee9a34542019-10-22 20:43:24 +0200472 /* ctx->reseed_counter contains the desired amount of entropy to
473 * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
474 * If it's -1, indicating that the entropy nonce length was not set
475 * explicitly, use a sufficiently large nonce for security. */
476 nonce_len = ( ctx->reseed_counter >= 0 ?
477 (size_t) ctx->reseed_counter :
478 good_nonce_len( ctx->entropy_len ) );
479
Gilles Peskine9be50982019-10-22 18:42:27 +0200480 /* Initialize with an empty key. */
Gilles Peskine8bf56132019-10-02 20:31:54 +0200481 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
482 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
483 {
484 return( ret );
485 }
486
Gilles Peskinee9a34542019-10-22 20:43:24 +0200487 /* Do the initial seeding. */
Gilles Peskine9be50982019-10-22 18:42:27 +0200488 if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len,
Gilles Peskinee9a34542019-10-22 20:43:24 +0200489 nonce_len ) ) != 0 )
Gilles Peskine8bf56132019-10-02 20:31:54 +0200490 {
491 return( ret );
492 }
493 return( 0 );
494}
495
Gilles Peskineed7da592018-08-03 20:16:52 +0200496/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
497 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
498 * implements
499 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
500 * -> working_state_after_reseed
501 * if required, then
502 * CTR_DRBG_Generate(working_state_after_reseed,
503 * requested_number_of_bits, additional_input)
504 * -> status, returned_bits, new_working_state
505 * with inputs
506 * ctx contains working_state
507 * requested_number_of_bits = 8 * output_len
508 * additional[:add_len] = additional_input
509 * and entropy_input comes from calling ctx->f_entropy
510 * and with outputs
511 * status = SUCCESS (this function does the reseed internally)
512 * returned_bits = output[:output_len]
513 * ctx contains new_working_state
514 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200515int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000516 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000517 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000518{
519 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200520 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
521 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000522 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200523 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000524 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000525 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000526
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200527 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
528 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000529
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200530 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
531 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000532
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200533 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000534
535 if( ctx->reseed_counter > ctx->reseed_interval ||
536 ctx->prediction_resistance )
537 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200538 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300539 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000540 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300541 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000542 add_len = 0;
543 }
544
545 if( add_len > 0 )
546 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300547 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200548 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300549 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200550 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000551 }
552
553 while( output_len > 0 )
554 {
555 /*
556 * Increase counter
557 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200558 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000559 if( ++ctx->counter[i - 1] != 0 )
560 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000561
562 /*
563 * Crypt counter block
564 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100565 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
566 ctx->counter, tmp ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300567 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200568 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300569 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000570
Hanno Beckera08651f2018-10-05 09:38:59 +0100571 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE )
572 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000573 /*
574 * Copy random block to destination
575 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000576 memcpy( p, tmp, use_len );
577 p += use_len;
578 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000579 }
580
Dvir Markovich1b364992017-06-26 13:43:34 +0300581 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200582 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000583
584 ctx->reseed_counter++;
585
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200586exit:
587 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
588 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
Gilles Peskineafaee1c2019-11-28 09:45:32 +0100589 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000590}
591
Hanno Beckera08651f2018-10-05 09:38:59 +0100592int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output,
593 size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000594{
Janos Follath24eed8d2019-11-22 13:21:35 +0000595 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100596 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
597
598#if defined(MBEDTLS_THREADING_C)
599 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
600 return( ret );
601#endif
602
603 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
604
605#if defined(MBEDTLS_THREADING_C)
606 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
607 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
608#endif
609
610 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000611}
612
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200613#if defined(MBEDTLS_FS_IO)
Hanno Beckera08651f2018-10-05 09:38:59 +0100614int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx,
615 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000616{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200617 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000618 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200619 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000620
621 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200622 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000623
Hanno Beckera08651f2018-10-05 09:38:59 +0100624 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf,
625 MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200626 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000627
Hanno Beckera08651f2018-10-05 09:38:59 +0100628 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) !=
629 MBEDTLS_CTR_DRBG_MAX_INPUT )
630 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200631 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Hanno Beckera08651f2018-10-05 09:38:59 +0100632 }
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100633 else
Hanno Beckera08651f2018-10-05 09:38:59 +0100634 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100635 ret = 0;
Hanno Beckera08651f2018-10-05 09:38:59 +0100636 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000637
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100638exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500639 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200640
Paul Bakkerfc754a92011-12-05 13:23:51 +0000641 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200642 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000643}
644
Hanno Beckera08651f2018-10-05 09:38:59 +0100645int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx,
646 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000647{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100648 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200649 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000650 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200651 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200652 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000653
654 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200655 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000656
Gilles Peskine82204662018-09-11 18:43:09 +0200657 n = fread( buf, 1, sizeof( buf ), f );
658 if( fread( &c, 1, 1, f ) != 0 )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100659 {
Gilles Peskine82204662018-09-11 18:43:09 +0200660 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
661 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100662 }
Gilles Peskine82204662018-09-11 18:43:09 +0200663 if( n == 0 || ferror( f ) )
664 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100665 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200666 goto exit;
667 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000668 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200669 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200670
Gilles Peskine82204662018-09-11 18:43:09 +0200671 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
672
673exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500674 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200675 if( f != NULL )
676 fclose( f );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100677 if( ret != 0 )
678 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200679 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000680}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200681#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000682
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200683#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000684
ENT\stroej170f63d02020-12-28 08:50:23 -0600685/* The CTR_DRBG NIST test vectors used here are available at
686 * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip
687 *
688 * The parameters used to derive the test data are:
689 *
690 * [AES-128 use df]
691 * [PredictionResistance = True/False]
692 * [EntropyInputLen = 128]
693 * [NonceLen = 64]
694 * [PersonalizationStringLen = 128]
695 * [AdditionalInputLen = 0]
696 * [ReturnedBitsLen = 512]
697 *
698 * [AES-256 use df]
699 * [PredictionResistance = True/False]
700 * [EntropyInputLen = 256]
701 * [NonceLen = 128]
702 * [PersonalizationStringLen = 256]
703 * [AdditionalInputLen = 0]
704 * [ReturnedBitsLen = 512]
705 *
706 */
707
Gilles Peskine02e79a42019-10-07 17:06:06 +0200708#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
ENT\stroej1df307002020-12-26 12:41:04 -0600709static const unsigned char entropy_source_pr[] =
710 { 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb,
711 0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92,
712 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8,
713 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20,
714 0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0,
715 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad,
716 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200717
ENT\stroej1df307002020-12-26 12:41:04 -0600718static const unsigned char entropy_source_nopr[] =
719 { 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45,
720 0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9,
721 0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20,
722 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f,
723 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c };
724
stroebeljcd4de1b52021-01-04 18:14:32 -0600725static const unsigned char pers_pr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600726 { 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a,
727 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad };
728
stroebeljcd4de1b52021-01-04 18:14:32 -0600729static const unsigned char pers_nopr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600730 { 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c,
731 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f };
732
733static const unsigned char result_pr[] =
734 { 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66,
735 0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff,
736 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10,
737 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30,
738 0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4,
739 0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc,
740 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06,
741 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf };
742
743static const unsigned char result_nopr[] =
744 { 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13,
745 0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0,
746 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf,
747 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2,
748 0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7,
749 0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2,
750 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02,
751 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200752#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000753
ENT\stroej1df307002020-12-26 12:41:04 -0600754static const unsigned char entropy_source_pr[] =
755 { 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49,
756 0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a,
757 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85,
758 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e,
759 0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15,
760 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45,
761 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8,
762 0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c,
763 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3,
764 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce,
765 0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e,
766 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76,
767 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77,
768 0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe };
769
770static const unsigned char entropy_source_nopr[] =
771 { 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d,
772 0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0,
773 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73,
774 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c,
775 0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2,
776 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1,
777 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a,
778 0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb,
779 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a,
780 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 };
781
stroebeljcd4de1b52021-01-04 18:14:32 -0600782static const unsigned char pers_pr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600783 { 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33,
784 0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e,
785 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0,
786 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 };
787
stroebeljcd4de1b52021-01-04 18:14:32 -0600788static const unsigned char pers_nopr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600789 { 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29,
790 0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf,
791 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb,
792 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b };
793
794static const unsigned char result_pr[] =
795 { 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85,
796 0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d,
797 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62,
798 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d,
799 0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb,
800 0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39,
801 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40,
802 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 };
803
804static const unsigned char result_nopr[] =
805 { 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad,
806 0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3,
807 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b,
808 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14,
809 0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54,
810 0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30,
811 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a,
812 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200813#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000814
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100815static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200816static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
817 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000818{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100819 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000820 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100821 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000822 return( 0 );
823}
824
Paul Bakker7dc4c442014-02-01 22:50:26 +0100825#define CHK( c ) if( (c) != 0 ) \
826 { \
827 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200828 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100829 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100830 }
831
stroebeljcd4de1b52021-01-04 18:14:32 -0600832#define SELF_TEST_OUPUT_DISCARD_LENGTH 64
833
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000834/*
835 * Checkup routine
836 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200837int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000838{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200839 mbedtls_ctr_drbg_context ctx;
stroebeljcd4de1b52021-01-04 18:14:32 -0600840 unsigned char buf[ sizeof( result_pr ) ];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000841
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200842 mbedtls_ctr_drbg_init( &ctx );
843
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000844 /*
845 * Based on a NIST CTR_DRBG test vector (PR = True)
846 */
847 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200848 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000849
850 test_offset = 0;
ENT\stroej1df307002020-12-26 12:41:04 -0600851 mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE );
stroebeljcd4de1b52021-01-04 18:14:32 -0600852 mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200853 CHK( mbedtls_ctr_drbg_seed( &ctx,
854 ctr_drbg_self_test_entropy,
855 (void *) entropy_source_pr,
stroebeljcd4de1b52021-01-04 18:14:32 -0600856 pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200857 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
stroebeljcd4de1b52021-01-04 18:14:32 -0600858 CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUPUT_DISCARD_LENGTH ) );
859 CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_pr ) ) );
860 CHK( memcmp( buf, result_pr, sizeof( result_pr ) ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000861
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100862 mbedtls_ctr_drbg_free( &ctx );
863
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000864 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200865 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000866
867 /*
868 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
869 */
870 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200871 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000872
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100873 mbedtls_ctr_drbg_init( &ctx );
874
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000875 test_offset = 0;
ENT\stroej1df307002020-12-26 12:41:04 -0600876 mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
stroebeljcd4de1b52021-01-04 18:14:32 -0600877 mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200878 CHK( mbedtls_ctr_drbg_seed( &ctx,
879 ctr_drbg_self_test_entropy,
880 (void *) entropy_source_nopr,
stroebeljcd4de1b52021-01-04 18:14:32 -0600881 pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200882 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
stroebeljcd4de1b52021-01-04 18:14:32 -0600883 CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUPUT_DISCARD_LENGTH ) );
884 CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_nopr ) ) );
885 CHK( memcmp( buf, result_nopr, sizeof( result_nopr ) ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000886
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100887 mbedtls_ctr_drbg_free( &ctx );
888
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000889 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200890 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000891
892 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200893 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000894
895 return( 0 );
896}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200897#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000898
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200899#endif /* MBEDTLS_CTR_DRBG_C */