blob: 75103a3992fbc3d98d3e74a3485f5952a078f830 [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 mbedtls_aes_init( &ctx->aes_ctx );
453
454 ctx->f_entropy = f_entropy;
455 ctx->p_entropy = p_entropy;
456
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200457 if( ctx->entropy_len == 0 )
458 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskinee9a34542019-10-22 20:43:24 +0200459 /* ctx->reseed_counter contains the desired amount of entropy to
460 * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
461 * If it's -1, indicating that the entropy nonce length was not set
462 * explicitly, use a sufficiently large nonce for security. */
463 nonce_len = ( ctx->reseed_counter >= 0 ?
464 (size_t) ctx->reseed_counter :
465 good_nonce_len( ctx->entropy_len ) );
466
Gilles Peskine9be50982019-10-22 18:42:27 +0200467 /* Initialize with an empty key. */
Gilles Peskine8bf56132019-10-02 20:31:54 +0200468 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
469 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
470 {
471 return( ret );
472 }
473
Gilles Peskinee9a34542019-10-22 20:43:24 +0200474 /* Do the initial seeding. */
Gilles Peskine9be50982019-10-22 18:42:27 +0200475 if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len,
Gilles Peskinee9a34542019-10-22 20:43:24 +0200476 nonce_len ) ) != 0 )
Gilles Peskine8bf56132019-10-02 20:31:54 +0200477 {
478 return( ret );
479 }
480 return( 0 );
481}
482
Gilles Peskineed7da592018-08-03 20:16:52 +0200483/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
484 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
485 * implements
486 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
487 * -> working_state_after_reseed
488 * if required, then
489 * CTR_DRBG_Generate(working_state_after_reseed,
490 * requested_number_of_bits, additional_input)
491 * -> status, returned_bits, new_working_state
492 * with inputs
493 * ctx contains working_state
494 * requested_number_of_bits = 8 * output_len
495 * additional[:add_len] = additional_input
496 * and entropy_input comes from calling ctx->f_entropy
497 * and with outputs
498 * status = SUCCESS (this function does the reseed internally)
499 * returned_bits = output[:output_len]
500 * ctx contains new_working_state
501 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200502int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000503 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000504 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000505{
506 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200507 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
508 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000509 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200510 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000511 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000512 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000513
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200514 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
515 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000516
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200517 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
518 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000519
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200520 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000521
522 if( ctx->reseed_counter > ctx->reseed_interval ||
523 ctx->prediction_resistance )
524 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200525 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300526 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000527 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300528 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000529 add_len = 0;
530 }
531
532 if( add_len > 0 )
533 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300534 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200535 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300536 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200537 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000538 }
539
540 while( output_len > 0 )
541 {
542 /*
543 * Increase counter
544 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200545 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000546 if( ++ctx->counter[i - 1] != 0 )
547 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000548
549 /*
550 * Crypt counter block
551 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100552 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
553 ctx->counter, tmp ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300554 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200555 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300556 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000557
Hanno Beckera08651f2018-10-05 09:38:59 +0100558 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE )
559 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000560 /*
561 * Copy random block to destination
562 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000563 memcpy( p, tmp, use_len );
564 p += use_len;
565 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000566 }
567
Dvir Markovich1b364992017-06-26 13:43:34 +0300568 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200569 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000570
571 ctx->reseed_counter++;
572
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200573exit:
574 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
575 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
Gilles Peskineafaee1c2019-11-28 09:45:32 +0100576 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000577}
578
Hanno Beckera08651f2018-10-05 09:38:59 +0100579int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output,
580 size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000581{
Janos Follath24eed8d2019-11-22 13:21:35 +0000582 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100583 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
584
585#if defined(MBEDTLS_THREADING_C)
586 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
587 return( ret );
588#endif
589
590 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
591
592#if defined(MBEDTLS_THREADING_C)
593 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
594 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
595#endif
596
597 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000598}
599
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200600#if defined(MBEDTLS_FS_IO)
Hanno Beckera08651f2018-10-05 09:38:59 +0100601int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx,
602 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000603{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200604 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000605 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200606 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000607
608 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200609 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000610
Gilles Peskineda0913b2022-06-30 17:03:40 +0200611 /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
612 mbedtls_setbuf( f, NULL );
613
Hanno Beckera08651f2018-10-05 09:38:59 +0100614 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf,
615 MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200616 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000617
Hanno Beckera08651f2018-10-05 09:38:59 +0100618 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) !=
619 MBEDTLS_CTR_DRBG_MAX_INPUT )
620 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200621 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Hanno Beckera08651f2018-10-05 09:38:59 +0100622 }
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100623 else
Hanno Beckera08651f2018-10-05 09:38:59 +0100624 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100625 ret = 0;
Hanno Beckera08651f2018-10-05 09:38:59 +0100626 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000627
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100628exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500629 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200630
Paul Bakkerfc754a92011-12-05 13:23:51 +0000631 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200632 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000633}
634
Hanno Beckera08651f2018-10-05 09:38:59 +0100635int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx,
636 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000637{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100638 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200639 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000640 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200641 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200642 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000643
644 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200645 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000646
Gilles Peskineda0913b2022-06-30 17:03:40 +0200647 /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
648 mbedtls_setbuf( f, NULL );
649
Gilles Peskine82204662018-09-11 18:43:09 +0200650 n = fread( buf, 1, sizeof( buf ), f );
651 if( fread( &c, 1, 1, f ) != 0 )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100652 {
Gilles Peskine82204662018-09-11 18:43:09 +0200653 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
654 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100655 }
Gilles Peskine82204662018-09-11 18:43:09 +0200656 if( n == 0 || ferror( f ) )
657 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100658 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200659 goto exit;
660 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000661 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200662 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200663
TRodziewicz26371e42021-06-08 16:45:41 +0200664 ret = mbedtls_ctr_drbg_update( ctx, buf, n );
Gilles Peskine82204662018-09-11 18:43:09 +0200665
666exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500667 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200668 if( f != NULL )
669 fclose( f );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100670 if( ret != 0 )
671 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200672 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000673}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200674#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000675
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200676#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000677
ENT\stroej170f63d02020-12-28 08:50:23 -0600678/* The CTR_DRBG NIST test vectors used here are available at
679 * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip
680 *
681 * The parameters used to derive the test data are:
682 *
683 * [AES-128 use df]
684 * [PredictionResistance = True/False]
685 * [EntropyInputLen = 128]
686 * [NonceLen = 64]
687 * [PersonalizationStringLen = 128]
688 * [AdditionalInputLen = 0]
689 * [ReturnedBitsLen = 512]
690 *
691 * [AES-256 use df]
692 * [PredictionResistance = True/False]
693 * [EntropyInputLen = 256]
694 * [NonceLen = 128]
695 * [PersonalizationStringLen = 256]
696 * [AdditionalInputLen = 0]
697 * [ReturnedBitsLen = 512]
698 *
699 */
700
Gilles Peskine02e79a42019-10-07 17:06:06 +0200701#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
ENT\stroej1df307002020-12-26 12:41:04 -0600702static const unsigned char entropy_source_pr[] =
703 { 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb,
704 0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92,
705 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8,
706 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20,
707 0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0,
708 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad,
709 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200710
ENT\stroej1df307002020-12-26 12:41:04 -0600711static const unsigned char entropy_source_nopr[] =
712 { 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45,
713 0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9,
714 0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20,
715 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f,
716 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c };
717
stroebeljcd4de1b52021-01-04 18:14:32 -0600718static const unsigned char pers_pr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600719 { 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a,
720 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad };
721
stroebeljcd4de1b52021-01-04 18:14:32 -0600722static const unsigned char pers_nopr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600723 { 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c,
724 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f };
725
726static const unsigned char result_pr[] =
727 { 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66,
728 0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff,
729 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10,
730 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30,
731 0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4,
732 0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc,
733 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06,
734 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf };
735
736static const unsigned char result_nopr[] =
737 { 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13,
738 0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0,
739 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf,
740 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2,
741 0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7,
742 0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2,
743 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02,
744 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200745#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000746
ENT\stroej1df307002020-12-26 12:41:04 -0600747static const unsigned char entropy_source_pr[] =
748 { 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49,
749 0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a,
750 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85,
751 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e,
752 0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15,
753 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45,
754 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8,
755 0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c,
756 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3,
757 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce,
758 0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e,
759 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76,
760 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77,
761 0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe };
762
763static const unsigned char entropy_source_nopr[] =
764 { 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d,
765 0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0,
766 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73,
767 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c,
768 0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2,
769 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1,
770 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a,
771 0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb,
772 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a,
773 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 };
774
stroebeljcd4de1b52021-01-04 18:14:32 -0600775static const unsigned char pers_pr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600776 { 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33,
777 0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e,
778 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0,
779 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 };
780
stroebeljcd4de1b52021-01-04 18:14:32 -0600781static const unsigned char pers_nopr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600782 { 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29,
783 0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf,
784 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb,
785 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b };
786
787static const unsigned char result_pr[] =
788 { 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85,
789 0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d,
790 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62,
791 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d,
792 0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb,
793 0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39,
794 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40,
795 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 };
796
797static const unsigned char result_nopr[] =
798 { 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad,
799 0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3,
800 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b,
801 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14,
802 0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54,
803 0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30,
804 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a,
805 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200806#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000807
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100808static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200809static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
810 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000811{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100812 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000813 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100814 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000815 return( 0 );
816}
817
Paul Bakker7dc4c442014-02-01 22:50:26 +0100818#define CHK( c ) if( (c) != 0 ) \
819 { \
820 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200821 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100822 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100823 }
824
bootstrap-prime6dbbf442022-05-17 19:30:44 -0400825#define SELF_TEST_OUTPUT_DISCARD_LENGTH 64
stroebeljcd4de1b52021-01-04 18:14:32 -0600826
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000827/*
828 * Checkup routine
829 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200830int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000831{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200832 mbedtls_ctr_drbg_context ctx;
stroebeljcd4de1b52021-01-04 18:14:32 -0600833 unsigned char buf[ sizeof( result_pr ) ];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000834
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200835 mbedtls_ctr_drbg_init( &ctx );
836
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000837 /*
838 * Based on a NIST CTR_DRBG test vector (PR = True)
839 */
840 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200841 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000842
843 test_offset = 0;
ENT\stroej1df307002020-12-26 12:41:04 -0600844 mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE );
stroebeljcd4de1b52021-01-04 18:14:32 -0600845 mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200846 CHK( mbedtls_ctr_drbg_seed( &ctx,
847 ctr_drbg_self_test_entropy,
848 (void *) entropy_source_pr,
stroebeljcd4de1b52021-01-04 18:14:32 -0600849 pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200850 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
bootstrap-prime6dbbf442022-05-17 19:30:44 -0400851 CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH ) );
stroebeljcd4de1b52021-01-04 18:14:32 -0600852 CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_pr ) ) );
853 CHK( memcmp( buf, result_pr, sizeof( result_pr ) ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000854
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100855 mbedtls_ctr_drbg_free( &ctx );
856
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000857 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200858 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000859
860 /*
861 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
862 */
863 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200864 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000865
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100866 mbedtls_ctr_drbg_init( &ctx );
867
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000868 test_offset = 0;
ENT\stroej1df307002020-12-26 12:41:04 -0600869 mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
stroebeljcd4de1b52021-01-04 18:14:32 -0600870 mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200871 CHK( mbedtls_ctr_drbg_seed( &ctx,
872 ctr_drbg_self_test_entropy,
873 (void *) entropy_source_nopr,
stroebeljcd4de1b52021-01-04 18:14:32 -0600874 pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200875 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
bootstrap-prime6dbbf442022-05-17 19:30:44 -0400876 CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH ) );
stroebeljcd4de1b52021-01-04 18:14:32 -0600877 CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_nopr ) ) );
878 CHK( memcmp( buf, result_nopr, sizeof( result_nopr ) ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000879
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100880 mbedtls_ctr_drbg_free( &ctx );
881
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000882 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200883 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000884
885 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200886 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000887
888 return( 0 );
889}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200890#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000891
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200892#endif /* MBEDTLS_CTR_DRBG_C */