blob: 8919c78a10bb49e1a8cae05081d63b3f9a6318eb [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 ) );
kXuan11e93102022-08-10 16:32:06 +080054 mbedtls_aes_init( &ctx->aes_ctx );
Gilles Peskinee9a34542019-10-22 20:43:24 +020055 /* Indicate that the entropy nonce length is not set explicitly.
56 * See mbedtls_ctr_drbg_set_nonce_len(). */
57 ctx->reseed_counter = -1;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010058
Gavin Acquroff6aceb512020-03-01 17:06:11 -080059 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020060}
61
Gavin Acquroff6aceb512020-03-01 17:06:11 -080062/*
63 * This function resets CTR_DRBG context to the state immediately
64 * after initial call of mbedtls_ctr_drbg_init().
65 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020066void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
Paul Bakkerfff03662014-06-18 16:21:25 +020067{
68 if( ctx == NULL )
69 return;
70
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010071#if defined(MBEDTLS_THREADING_C)
Gilles Peskineda290f92021-02-09 18:44:02 +010072 /* The mutex is initialized iff f_entropy is set. */
Gilles Peskinef4b34292021-01-30 13:05:32 +010073 if( ctx->f_entropy != NULL )
74 mbedtls_mutex_free( &ctx->mutex );
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010075#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020076 mbedtls_aes_free( &ctx->aes_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050077 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Gavin Acquroff6aceb512020-03-01 17:06:11 -080078 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
79 ctx->reseed_counter = -1;
Paul Bakkerfff03662014-06-18 16:21:25 +020080}
81
Hanno Beckera08651f2018-10-05 09:38:59 +010082void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx,
83 int resistance )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000084{
85 ctx->prediction_resistance = resistance;
86}
87
Hanno Beckera08651f2018-10-05 09:38:59 +010088void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx,
89 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000090{
91 ctx->entropy_len = len;
92}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +020093
Gilles Peskine9be50982019-10-22 18:42:27 +020094int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx,
95 size_t len )
96{
97 /* If mbedtls_ctr_drbg_seed() has already been called, it's
98 * too late. Return the error code that's closest to making sense. */
99 if( ctx->f_entropy != NULL )
100 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
101
102 if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
103 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
104#if SIZE_MAX > INT_MAX
105 /* This shouldn't be an issue because
106 * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible
107 * configuration, but make sure anyway. */
108 if( len > INT_MAX )
109 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
110#endif
111
112 /* For backward compatibility with Mbed TLS <= 2.19, store the
113 * entropy nonce length in a field that already exists, but isn't
114 * used until after the initial seeding. */
115 /* Due to the capping of len above, the value fits in an int. */
116 ctx->reseed_counter = (int) len;
117 return( 0 );
118}
119
Hanno Beckera08651f2018-10-05 09:38:59 +0100120void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx,
121 int interval )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000122{
123 ctx->reseed_interval = interval;
124}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200125
126static int block_cipher_df( unsigned char *output,
127 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000128{
Hanno Beckera08651f2018-10-05 09:38:59 +0100129 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
130 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200131 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
132 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
133 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100134 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200135 mbedtls_aes_context aes_ctx;
Dvir Markovich1b364992017-06-26 13:43:34 +0300136 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000137
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200138 int i, j;
139 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000140
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200141 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
142 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100143
Hanno Beckera08651f2018-10-05 09:38:59 +0100144 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
145 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200146 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000147
148 /*
149 * Construct IV (16 bytes) and S in buffer
150 * IV = Counter (in 32-bits) padded to 16 with zeroes
151 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
152 * data || 0x80
153 * (Total is padded to a multiple of 16-bytes with zeroes)
154 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200155 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Joe Subbiania5cb0d22021-08-23 11:35:25 +0100156 MBEDTLS_PUT_UINT32_BE( data_len, p, 0);
157 p += 4 + 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200158 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000159 memcpy( p, data, data_len );
160 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000161
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200162 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000163
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200164 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000165 key[i] = i;
166
Hanno Beckera08651f2018-10-05 09:38:59 +0100167 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key,
168 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300169 {
170 goto exit;
171 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000172
173 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200174 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000175 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200176 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000177 {
178 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200179 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000180 use_len = buf_len;
181
182 while( use_len > 0 )
183 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200184 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000185 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200186 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
187 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
188 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000189
Hanno Beckera08651f2018-10-05 09:38:59 +0100190 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
191 chain, chain ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300192 {
193 goto exit;
194 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000195 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200196
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200197 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000198
199 /*
200 * Update IV
201 */
202 buf[3]++;
203 }
204
205 /*
206 * Do final encryption with reduced data
207 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100208 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp,
209 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300210 {
211 goto exit;
212 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200213 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000214 p = output;
215
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200216 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000217 {
Hanno Beckera08651f2018-10-05 09:38:59 +0100218 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
219 iv, iv ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300220 {
221 goto exit;
222 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200223 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
224 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000225 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300226exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200227 mbedtls_aes_free( &aes_ctx );
Dvir Markovich1b364992017-06-26 13:43:34 +0300228 /*
229 * tidy up the stack
230 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500231 mbedtls_platform_zeroize( buf, sizeof( buf ) );
232 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
233 mbedtls_platform_zeroize( key, sizeof( key ) );
234 mbedtls_platform_zeroize( chain, sizeof( chain ) );
Dvir Markovich1b364992017-06-26 13:43:34 +0300235 if( 0 != ret )
236 {
237 /*
238 * wipe partial seed from memory
239 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500240 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
Dvir Markovich1b364992017-06-26 13:43:34 +0300241 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200242
Dvir Markovich1b364992017-06-26 13:43:34 +0300243 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000244}
245
Gilles Peskineed7da592018-08-03 20:16:52 +0200246/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
247 * ctr_drbg_update_internal(ctx, provided_data)
248 * implements
249 * CTR_DRBG_Update(provided_data, Key, V)
250 * with inputs and outputs
251 * ctx->aes_ctx = Key
252 * ctx->counter = V
253 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200254static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
Hanno Beckera08651f2018-10-05 09:38:59 +0100255 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000256{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200257 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000258 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000259 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300260 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000261
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200262 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000263
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200264 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000265 {
266 /*
267 * Increase counter
268 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200269 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000270 if( ++ctx->counter[i - 1] != 0 )
271 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000272
273 /*
274 * Crypt counter block
275 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100276 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
277 ctx->counter, p ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300278 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200279 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300280 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000281
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200282 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000283 }
284
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200285 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000286 tmp[i] ^= data[i];
287
288 /*
289 * Update key and counter
290 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100291 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp,
292 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300293 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200294 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300295 }
Hanno Beckera08651f2018-10-05 09:38:59 +0100296 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
297 MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000298
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200299exit:
300 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
301 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000302}
303
Gilles Peskineed7da592018-08-03 20:16:52 +0200304/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
TRodziewicz26371e42021-06-08 16:45:41 +0200305 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
Gilles Peskineed7da592018-08-03 20:16:52 +0200306 * implements
307 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
308 * security_strength) -> initial_working_state
309 * with inputs
310 * ctx->counter = all-bits-0
311 * ctx->aes_ctx = context from all-bits-0 key
312 * additional[:add_len] = entropy_input || nonce || personalization_string
313 * and with outputs
314 * ctx = initial_working_state
315 */
TRodziewicz26371e42021-06-08 16:45:41 +0200316int mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
Gilles Peskined9199932018-09-11 16:41:54 +0200317 const unsigned char *additional,
318 size_t add_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000319{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200320 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Janos Follath24eed8d2019-11-22 13:21:35 +0000321 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000322
Gilles Peskined9199932018-09-11 16:41:54 +0200323 if( add_len == 0 )
324 return( 0 );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100325
Gilles Peskined9199932018-09-11 16:41:54 +0200326 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
327 goto exit;
328 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
329 goto exit;
330
331exit:
332 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
333 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000334}
335
Gilles Peskineed7da592018-08-03 20:16:52 +0200336/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
Gilles Peskine9be50982019-10-22 18:42:27 +0200337 * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
Gilles Peskineed7da592018-08-03 20:16:52 +0200338 * implements
339 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
340 * -> new_working_state
341 * with inputs
342 * ctx contains working_state
343 * additional[:len] = additional_input
344 * and entropy_input comes from calling ctx->f_entropy
Gilles Peskine9be50982019-10-22 18:42:27 +0200345 * for (ctx->entropy_len + nonce_len) bytes
Gilles Peskineed7da592018-08-03 20:16:52 +0200346 * and with output
347 * ctx contains new_working_state
348 */
Gilles Peskine97f59ab2019-10-22 18:42:27 +0200349static int mbedtls_ctr_drbg_reseed_internal( mbedtls_ctr_drbg_context *ctx,
350 const unsigned char *additional,
351 size_t len,
352 size_t nonce_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000353{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200354 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000355 size_t seedlen = 0;
Janos Follath24eed8d2019-11-22 13:21:35 +0000356 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000357
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200358 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
359 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Gilles Peskine9be50982019-10-22 18:42:27 +0200360 if( nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
361 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
362 if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200363 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000364
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200365 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000366
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200367 /* Gather entropy_len bytes of entropy to seed state. */
368 if( 0 != ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000369 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200370 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000371 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000372 seedlen += ctx->entropy_len;
373
Gilles Peskine9be50982019-10-22 18:42:27 +0200374 /* Gather entropy for a nonce if requested. */
375 if( nonce_len != 0 )
376 {
ENT\stroej14b919862020-12-23 17:28:33 -0600377 if( 0 != ctx->f_entropy( ctx->p_entropy, seed + seedlen, nonce_len ) )
Gilles Peskine9be50982019-10-22 18:42:27 +0200378 {
379 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
380 }
381 seedlen += nonce_len;
382 }
383
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200384 /* Add additional data if provided. */
385 if( additional != NULL && len != 0 )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000386 {
387 memcpy( seed + seedlen, additional, len );
388 seedlen += len;
389 }
390
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200391 /* Reduce to 384 bits. */
Dvir Markovich1b364992017-06-26 13:43:34 +0300392 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200393 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000394
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200395 /* Update state. */
Dvir Markovich1b364992017-06-26 13:43:34 +0300396 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200397 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000398 ctx->reseed_counter = 1;
399
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200400exit:
401 mbedtls_platform_zeroize( seed, sizeof( seed ) );
402 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000403}
Paul Bakker9af723c2014-05-01 13:03:14 +0200404
Gilles Peskine9be50982019-10-22 18:42:27 +0200405int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
406 const unsigned char *additional, size_t len )
407{
408 return( mbedtls_ctr_drbg_reseed_internal( ctx, additional, len, 0 ) );
409}
410
Gilles Peskinee9a34542019-10-22 20:43:24 +0200411/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
412 * is sufficient to achieve the maximum security strength given the key
413 * size and entropy length. If there is enough entropy in the initial
414 * call to the entropy function to serve as both the entropy input and
415 * the nonce, don't make a second call to get a nonce. */
416static size_t good_nonce_len( size_t entropy_len )
417{
418 if( entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 )
419 return( 0 );
420 else
421 return( ( entropy_len + 1 ) / 2 );
422}
423
Gilles Peskine8bf56132019-10-02 20:31:54 +0200424/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
Gilles Peskine379561f2019-10-18 16:57:48 +0200425 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
Gilles Peskine8bf56132019-10-02 20:31:54 +0200426 * implements
427 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
428 * security_strength) -> initial_working_state
429 * with inputs
430 * custom[:len] = nonce || personalization_string
Gilles Peskine379561f2019-10-18 16:57:48 +0200431 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
Gilles Peskine8bf56132019-10-02 20:31:54 +0200432 * and with outputs
433 * ctx = initial_working_state
434 */
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200435int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
436 int (*f_entropy)(void *, unsigned char *, size_t),
437 void *p_entropy,
438 const unsigned char *custom,
439 size_t len )
Gilles Peskine8bf56132019-10-02 20:31:54 +0200440{
Janos Follath24eed8d2019-11-22 13:21:35 +0000441 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200442 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Gilles Peskinee9a34542019-10-22 20:43:24 +0200443 size_t nonce_len;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200444
445 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
446
Gilles Peskineda290f92021-02-09 18:44:02 +0100447 /* The mutex is initialized iff f_entropy is set. */
Gilles Peskinef4b34292021-01-30 13:05:32 +0100448#if defined(MBEDTLS_THREADING_C)
449 mbedtls_mutex_init( &ctx->mutex );
450#endif
451
Gilles Peskine8bf56132019-10-02 20:31:54 +0200452 ctx->f_entropy = f_entropy;
453 ctx->p_entropy = p_entropy;
454
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200455 if( ctx->entropy_len == 0 )
456 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskinee9a34542019-10-22 20:43:24 +0200457 /* ctx->reseed_counter contains the desired amount of entropy to
458 * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
459 * If it's -1, indicating that the entropy nonce length was not set
460 * explicitly, use a sufficiently large nonce for security. */
461 nonce_len = ( ctx->reseed_counter >= 0 ?
462 (size_t) ctx->reseed_counter :
463 good_nonce_len( ctx->entropy_len ) );
464
Gilles Peskine9be50982019-10-22 18:42:27 +0200465 /* Initialize with an empty key. */
Gilles Peskine8bf56132019-10-02 20:31:54 +0200466 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
467 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
468 {
469 return( ret );
470 }
471
Gilles Peskinee9a34542019-10-22 20:43:24 +0200472 /* Do the initial seeding. */
Gilles Peskine9be50982019-10-22 18:42:27 +0200473 if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len,
Gilles Peskinee9a34542019-10-22 20:43:24 +0200474 nonce_len ) ) != 0 )
Gilles Peskine8bf56132019-10-02 20:31:54 +0200475 {
476 return( ret );
477 }
478 return( 0 );
479}
480
Gilles Peskineed7da592018-08-03 20:16:52 +0200481/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
482 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
483 * implements
484 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
485 * -> working_state_after_reseed
486 * if required, then
487 * CTR_DRBG_Generate(working_state_after_reseed,
488 * requested_number_of_bits, additional_input)
489 * -> status, returned_bits, new_working_state
490 * with inputs
491 * ctx contains working_state
492 * requested_number_of_bits = 8 * output_len
493 * additional[:add_len] = additional_input
494 * and entropy_input comes from calling ctx->f_entropy
495 * and with outputs
496 * status = SUCCESS (this function does the reseed internally)
497 * returned_bits = output[:output_len]
498 * ctx contains new_working_state
499 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200500int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000501 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000502 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000503{
504 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200505 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
506 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000507 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200508 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000509 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000510 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000511
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200512 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
513 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000514
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200515 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
516 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000517
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200518 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000519
520 if( ctx->reseed_counter > ctx->reseed_interval ||
521 ctx->prediction_resistance )
522 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200523 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300524 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000525 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300526 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000527 add_len = 0;
528 }
529
530 if( add_len > 0 )
531 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300532 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200533 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300534 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200535 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000536 }
537
538 while( output_len > 0 )
539 {
540 /*
541 * Increase counter
542 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200543 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000544 if( ++ctx->counter[i - 1] != 0 )
545 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000546
547 /*
548 * Crypt counter block
549 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100550 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
551 ctx->counter, tmp ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300552 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200553 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300554 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000555
Hanno Beckera08651f2018-10-05 09:38:59 +0100556 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE )
557 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000558 /*
559 * Copy random block to destination
560 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000561 memcpy( p, tmp, use_len );
562 p += use_len;
563 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000564 }
565
Dvir Markovich1b364992017-06-26 13:43:34 +0300566 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200567 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000568
569 ctx->reseed_counter++;
570
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200571exit:
572 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
573 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
Gilles Peskineafaee1c2019-11-28 09:45:32 +0100574 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000575}
576
Hanno Beckera08651f2018-10-05 09:38:59 +0100577int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output,
578 size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000579{
Janos Follath24eed8d2019-11-22 13:21:35 +0000580 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100581 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
582
583#if defined(MBEDTLS_THREADING_C)
584 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
585 return( ret );
586#endif
587
588 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
589
590#if defined(MBEDTLS_THREADING_C)
591 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
592 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
593#endif
594
595 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000596}
597
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200598#if defined(MBEDTLS_FS_IO)
Hanno Beckera08651f2018-10-05 09:38:59 +0100599int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx,
600 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000601{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200602 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000603 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200604 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000605
606 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200607 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000608
Gilles Peskineda0913b2022-06-30 17:03:40 +0200609 /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
610 mbedtls_setbuf( f, NULL );
611
Hanno Beckera08651f2018-10-05 09:38:59 +0100612 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf,
613 MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200614 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000615
Hanno Beckera08651f2018-10-05 09:38:59 +0100616 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) !=
617 MBEDTLS_CTR_DRBG_MAX_INPUT )
618 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200619 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Hanno Beckera08651f2018-10-05 09:38:59 +0100620 }
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100621 else
Hanno Beckera08651f2018-10-05 09:38:59 +0100622 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100623 ret = 0;
Hanno Beckera08651f2018-10-05 09:38:59 +0100624 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000625
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100626exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500627 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200628
Paul Bakkerfc754a92011-12-05 13:23:51 +0000629 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200630 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000631}
632
Hanno Beckera08651f2018-10-05 09:38:59 +0100633int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx,
634 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000635{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100636 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200637 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000638 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200639 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200640 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000641
642 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200643 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000644
Gilles Peskineda0913b2022-06-30 17:03:40 +0200645 /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
646 mbedtls_setbuf( f, NULL );
647
Gilles Peskine82204662018-09-11 18:43:09 +0200648 n = fread( buf, 1, sizeof( buf ), f );
649 if( fread( &c, 1, 1, f ) != 0 )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100650 {
Gilles Peskine82204662018-09-11 18:43:09 +0200651 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
652 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100653 }
Gilles Peskine82204662018-09-11 18:43:09 +0200654 if( n == 0 || ferror( f ) )
655 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100656 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200657 goto exit;
658 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000659 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200660 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200661
TRodziewicz26371e42021-06-08 16:45:41 +0200662 ret = mbedtls_ctr_drbg_update( ctx, buf, n );
Gilles Peskine82204662018-09-11 18:43:09 +0200663
664exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500665 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200666 if( f != NULL )
667 fclose( f );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100668 if( ret != 0 )
669 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200670 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000671}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200672#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000673
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200674#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000675
ENT\stroej170f63d02020-12-28 08:50:23 -0600676/* The CTR_DRBG NIST test vectors used here are available at
677 * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip
678 *
679 * The parameters used to derive the test data are:
680 *
681 * [AES-128 use df]
682 * [PredictionResistance = True/False]
683 * [EntropyInputLen = 128]
684 * [NonceLen = 64]
685 * [PersonalizationStringLen = 128]
686 * [AdditionalInputLen = 0]
687 * [ReturnedBitsLen = 512]
688 *
689 * [AES-256 use df]
690 * [PredictionResistance = True/False]
691 * [EntropyInputLen = 256]
692 * [NonceLen = 128]
693 * [PersonalizationStringLen = 256]
694 * [AdditionalInputLen = 0]
695 * [ReturnedBitsLen = 512]
696 *
697 */
698
Gilles Peskine02e79a42019-10-07 17:06:06 +0200699#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
ENT\stroej1df307002020-12-26 12:41:04 -0600700static const unsigned char entropy_source_pr[] =
701 { 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb,
702 0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92,
703 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8,
704 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20,
705 0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0,
706 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad,
707 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200708
ENT\stroej1df307002020-12-26 12:41:04 -0600709static const unsigned char entropy_source_nopr[] =
710 { 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45,
711 0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9,
712 0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20,
713 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f,
714 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c };
715
stroebeljcd4de1b52021-01-04 18:14:32 -0600716static const unsigned char pers_pr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600717 { 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a,
718 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad };
719
stroebeljcd4de1b52021-01-04 18:14:32 -0600720static const unsigned char pers_nopr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600721 { 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c,
722 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f };
723
724static const unsigned char result_pr[] =
725 { 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66,
726 0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff,
727 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10,
728 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30,
729 0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4,
730 0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc,
731 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06,
732 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf };
733
734static const unsigned char result_nopr[] =
735 { 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13,
736 0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0,
737 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf,
738 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2,
739 0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7,
740 0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2,
741 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02,
742 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200743#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000744
ENT\stroej1df307002020-12-26 12:41:04 -0600745static const unsigned char entropy_source_pr[] =
746 { 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49,
747 0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a,
748 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85,
749 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e,
750 0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15,
751 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45,
752 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8,
753 0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c,
754 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3,
755 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce,
756 0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e,
757 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76,
758 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77,
759 0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe };
760
761static const unsigned char entropy_source_nopr[] =
762 { 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d,
763 0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0,
764 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73,
765 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c,
766 0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2,
767 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1,
768 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a,
769 0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb,
770 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a,
771 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 };
772
stroebeljcd4de1b52021-01-04 18:14:32 -0600773static const unsigned char pers_pr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600774 { 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33,
775 0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e,
776 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0,
777 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 };
778
stroebeljcd4de1b52021-01-04 18:14:32 -0600779static const unsigned char pers_nopr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600780 { 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29,
781 0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf,
782 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb,
783 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b };
784
785static const unsigned char result_pr[] =
786 { 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85,
787 0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d,
788 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62,
789 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d,
790 0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb,
791 0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39,
792 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40,
793 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 };
794
795static const unsigned char result_nopr[] =
796 { 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad,
797 0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3,
798 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b,
799 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14,
800 0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54,
801 0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30,
802 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a,
803 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200804#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000805
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100806static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200807static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
808 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000809{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100810 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000811 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100812 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000813 return( 0 );
814}
815
Paul Bakker7dc4c442014-02-01 22:50:26 +0100816#define CHK( c ) if( (c) != 0 ) \
817 { \
818 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200819 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100820 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100821 }
822
bootstrap-prime6dbbf442022-05-17 19:30:44 -0400823#define SELF_TEST_OUTPUT_DISCARD_LENGTH 64
stroebeljcd4de1b52021-01-04 18:14:32 -0600824
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000825/*
826 * Checkup routine
827 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200828int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000829{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200830 mbedtls_ctr_drbg_context ctx;
stroebeljcd4de1b52021-01-04 18:14:32 -0600831 unsigned char buf[ sizeof( result_pr ) ];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000832
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200833 mbedtls_ctr_drbg_init( &ctx );
834
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000835 /*
836 * Based on a NIST CTR_DRBG test vector (PR = True)
837 */
838 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200839 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000840
841 test_offset = 0;
ENT\stroej1df307002020-12-26 12:41:04 -0600842 mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE );
stroebeljcd4de1b52021-01-04 18:14:32 -0600843 mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200844 CHK( mbedtls_ctr_drbg_seed( &ctx,
845 ctr_drbg_self_test_entropy,
846 (void *) entropy_source_pr,
stroebeljcd4de1b52021-01-04 18:14:32 -0600847 pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200848 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
bootstrap-prime6dbbf442022-05-17 19:30:44 -0400849 CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH ) );
stroebeljcd4de1b52021-01-04 18:14:32 -0600850 CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_pr ) ) );
851 CHK( memcmp( buf, result_pr, sizeof( result_pr ) ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000852
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100853 mbedtls_ctr_drbg_free( &ctx );
854
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000855 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200856 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000857
858 /*
859 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
860 */
861 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200862 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000863
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100864 mbedtls_ctr_drbg_init( &ctx );
865
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000866 test_offset = 0;
ENT\stroej1df307002020-12-26 12:41:04 -0600867 mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
stroebeljcd4de1b52021-01-04 18:14:32 -0600868 mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200869 CHK( mbedtls_ctr_drbg_seed( &ctx,
870 ctr_drbg_self_test_entropy,
871 (void *) entropy_source_nopr,
stroebeljcd4de1b52021-01-04 18:14:32 -0600872 pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200873 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
bootstrap-prime6dbbf442022-05-17 19:30:44 -0400874 CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH ) );
stroebeljcd4de1b52021-01-04 18:14:32 -0600875 CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_nopr ) ) );
876 CHK( memcmp( buf, result_nopr, sizeof( result_nopr ) ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000877
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100878 mbedtls_ctr_drbg_free( &ctx );
879
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000880 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200881 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000882
883 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200884 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000885
886 return( 0 );
887}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200888#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000889
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200890#endif /* MBEDTLS_CTR_DRBG_C */