blob: 71c48afd2850dbe0349535a5ceacd8becfade86e [file] [log] [blame]
Paul Bakker0e04d0e2011-11-27 14:46:59 +00001/*
2 * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakker0e04d0e2011-11-27 14:46:59 +000018 */
19/*
Paul Sokolovsky8d6d8c82018-02-10 11:11:41 +020020 * The NIST SP 800-90 DRBGs are described in the following publication.
Paul Bakker0e04d0e2011-11-27 14:46:59 +000021 *
22 * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
23 */
24
Gilles Peskinedb09ef62020-06-03 01:43:33 +020025#include "common.h"
Paul Bakker0e04d0e2011-11-27 14:46:59 +000026
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020027#if defined(MBEDTLS_CTR_DRBG_C)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000028
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000029#include "mbedtls/ctr_drbg.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050030#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000031#include "mbedtls/error.h"
Paul Bakker0e04d0e2011-11-27 14:46:59 +000032
Rich Evans00ab4702015-02-06 13:43:58 +000033#include <string.h>
34
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020035#if defined(MBEDTLS_FS_IO)
Paul Bakkerfc754a92011-12-05 13:23:51 +000036#include <stdio.h>
37#endif
38
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000039#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010040
Paul Bakker18d32912011-12-10 21:42:49 +000041/*
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020042 * CTR_DRBG context initialization
43 */
44void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
45{
46 memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
kXuan11e93102022-08-10 16:32:06 +080047 mbedtls_aes_init( &ctx->aes_ctx );
Gilles Peskinee9a34542019-10-22 20:43:24 +020048 /* Indicate that the entropy nonce length is not set explicitly.
49 * See mbedtls_ctr_drbg_set_nonce_len(). */
50 ctx->reseed_counter = -1;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010051
Gavin Acquroff6aceb512020-03-01 17:06:11 -080052 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020053}
54
Gavin Acquroff6aceb512020-03-01 17:06:11 -080055/*
56 * This function resets CTR_DRBG context to the state immediately
57 * after initial call of mbedtls_ctr_drbg_init().
58 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020059void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
Paul Bakkerfff03662014-06-18 16:21:25 +020060{
61 if( ctx == NULL )
62 return;
63
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010064#if defined(MBEDTLS_THREADING_C)
Gilles Peskineda290f92021-02-09 18:44:02 +010065 /* The mutex is initialized iff f_entropy is set. */
Gilles Peskinef4b34292021-01-30 13:05:32 +010066 if( ctx->f_entropy != NULL )
67 mbedtls_mutex_free( &ctx->mutex );
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010068#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020069 mbedtls_aes_free( &ctx->aes_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050070 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Gavin Acquroff6aceb512020-03-01 17:06:11 -080071 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
72 ctx->reseed_counter = -1;
Paul Bakkerfff03662014-06-18 16:21:25 +020073}
74
Hanno Beckera08651f2018-10-05 09:38:59 +010075void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx,
76 int resistance )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000077{
78 ctx->prediction_resistance = resistance;
79}
80
Hanno Beckera08651f2018-10-05 09:38:59 +010081void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx,
82 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000083{
84 ctx->entropy_len = len;
85}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +020086
Gilles Peskine9be50982019-10-22 18:42:27 +020087int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx,
88 size_t len )
89{
90 /* If mbedtls_ctr_drbg_seed() has already been called, it's
91 * too late. Return the error code that's closest to making sense. */
92 if( ctx->f_entropy != NULL )
93 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
94
95 if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
96 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
97#if SIZE_MAX > INT_MAX
98 /* This shouldn't be an issue because
99 * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible
100 * configuration, but make sure anyway. */
101 if( len > INT_MAX )
102 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
103#endif
104
105 /* For backward compatibility with Mbed TLS <= 2.19, store the
106 * entropy nonce length in a field that already exists, but isn't
107 * used until after the initial seeding. */
108 /* Due to the capping of len above, the value fits in an int. */
109 ctx->reseed_counter = (int) len;
110 return( 0 );
111}
112
Hanno Beckera08651f2018-10-05 09:38:59 +0100113void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx,
114 int interval )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000115{
116 ctx->reseed_interval = interval;
117}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200118
119static int block_cipher_df( unsigned char *output,
120 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000121{
Hanno Beckera08651f2018-10-05 09:38:59 +0100122 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
123 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200124 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
125 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
126 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100127 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200128 mbedtls_aes_context aes_ctx;
Dvir Markovich1b364992017-06-26 13:43:34 +0300129 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000130
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200131 int i, j;
132 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000133
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200134 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
135 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100136
Hanno Beckera08651f2018-10-05 09:38:59 +0100137 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
138 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200139 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000140
141 /*
142 * Construct IV (16 bytes) and S in buffer
143 * IV = Counter (in 32-bits) padded to 16 with zeroes
144 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
145 * data || 0x80
146 * (Total is padded to a multiple of 16-bytes with zeroes)
147 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200148 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Joe Subbiania5cb0d22021-08-23 11:35:25 +0100149 MBEDTLS_PUT_UINT32_BE( data_len, p, 0);
150 p += 4 + 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200151 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000152 memcpy( p, data, data_len );
153 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000154
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200155 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000156
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200157 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000158 key[i] = i;
159
Hanno Beckera08651f2018-10-05 09:38:59 +0100160 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key,
161 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300162 {
163 goto exit;
164 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000165
166 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200167 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000168 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200169 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000170 {
171 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200172 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000173 use_len = buf_len;
174
175 while( use_len > 0 )
176 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200177 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000178 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200179 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
180 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
181 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000182
Hanno Beckera08651f2018-10-05 09:38:59 +0100183 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
184 chain, chain ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300185 {
186 goto exit;
187 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000188 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200189
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200190 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000191
192 /*
193 * Update IV
194 */
195 buf[3]++;
196 }
197
198 /*
199 * Do final encryption with reduced data
200 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100201 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp,
202 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300203 {
204 goto exit;
205 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200206 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000207 p = output;
208
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200209 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000210 {
Hanno Beckera08651f2018-10-05 09:38:59 +0100211 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
212 iv, iv ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300213 {
214 goto exit;
215 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200216 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
217 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000218 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300219exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200220 mbedtls_aes_free( &aes_ctx );
Dvir Markovich1b364992017-06-26 13:43:34 +0300221 /*
222 * tidy up the stack
223 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500224 mbedtls_platform_zeroize( buf, sizeof( buf ) );
225 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
226 mbedtls_platform_zeroize( key, sizeof( key ) );
227 mbedtls_platform_zeroize( chain, sizeof( chain ) );
Dvir Markovich1b364992017-06-26 13:43:34 +0300228 if( 0 != ret )
229 {
230 /*
231 * wipe partial seed from memory
232 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500233 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
Dvir Markovich1b364992017-06-26 13:43:34 +0300234 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200235
Dvir Markovich1b364992017-06-26 13:43:34 +0300236 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000237}
238
Gilles Peskineed7da592018-08-03 20:16:52 +0200239/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
240 * ctr_drbg_update_internal(ctx, provided_data)
241 * implements
242 * CTR_DRBG_Update(provided_data, Key, V)
243 * with inputs and outputs
244 * ctx->aes_ctx = Key
245 * ctx->counter = V
246 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200247static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
Hanno Beckera08651f2018-10-05 09:38:59 +0100248 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000249{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200250 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000251 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000252 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300253 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000254
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200255 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000256
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200257 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000258 {
259 /*
260 * Increase counter
261 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200262 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000263 if( ++ctx->counter[i - 1] != 0 )
264 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000265
266 /*
267 * Crypt counter block
268 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100269 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
270 ctx->counter, p ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300271 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200272 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300273 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000274
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200275 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000276 }
277
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200278 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000279 tmp[i] ^= data[i];
280
281 /*
282 * Update key and counter
283 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100284 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp,
285 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300286 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200287 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300288 }
Hanno Beckera08651f2018-10-05 09:38:59 +0100289 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
290 MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000291
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200292exit:
293 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
294 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000295}
296
Gilles Peskineed7da592018-08-03 20:16:52 +0200297/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
TRodziewicz26371e42021-06-08 16:45:41 +0200298 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
Gilles Peskineed7da592018-08-03 20:16:52 +0200299 * implements
300 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
301 * security_strength) -> initial_working_state
302 * with inputs
303 * ctx->counter = all-bits-0
304 * ctx->aes_ctx = context from all-bits-0 key
305 * additional[:add_len] = entropy_input || nonce || personalization_string
306 * and with outputs
307 * ctx = initial_working_state
308 */
TRodziewicz26371e42021-06-08 16:45:41 +0200309int mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
Gilles Peskined9199932018-09-11 16:41:54 +0200310 const unsigned char *additional,
311 size_t add_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000312{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200313 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Janos Follath24eed8d2019-11-22 13:21:35 +0000314 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000315
Gilles Peskined9199932018-09-11 16:41:54 +0200316 if( add_len == 0 )
317 return( 0 );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100318
Gilles Peskined9199932018-09-11 16:41:54 +0200319 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
320 goto exit;
321 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
322 goto exit;
323
324exit:
325 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
326 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000327}
328
Gilles Peskineed7da592018-08-03 20:16:52 +0200329/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
Gilles Peskine9be50982019-10-22 18:42:27 +0200330 * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
Gilles Peskineed7da592018-08-03 20:16:52 +0200331 * implements
332 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
333 * -> new_working_state
334 * with inputs
335 * ctx contains working_state
336 * additional[:len] = additional_input
337 * and entropy_input comes from calling ctx->f_entropy
Gilles Peskine9be50982019-10-22 18:42:27 +0200338 * for (ctx->entropy_len + nonce_len) bytes
Gilles Peskineed7da592018-08-03 20:16:52 +0200339 * and with output
340 * ctx contains new_working_state
341 */
Gilles Peskine97f59ab2019-10-22 18:42:27 +0200342static int mbedtls_ctr_drbg_reseed_internal( mbedtls_ctr_drbg_context *ctx,
343 const unsigned char *additional,
344 size_t len,
345 size_t nonce_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000346{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200347 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000348 size_t seedlen = 0;
Janos Follath24eed8d2019-11-22 13:21:35 +0000349 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000350
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200351 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
352 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Gilles Peskine9be50982019-10-22 18:42:27 +0200353 if( nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
354 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
355 if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200356 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000357
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200358 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000359
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200360 /* Gather entropy_len bytes of entropy to seed state. */
361 if( 0 != ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000362 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200363 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000364 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000365 seedlen += ctx->entropy_len;
366
Gilles Peskine9be50982019-10-22 18:42:27 +0200367 /* Gather entropy for a nonce if requested. */
368 if( nonce_len != 0 )
369 {
ENT\stroej14b919862020-12-23 17:28:33 -0600370 if( 0 != ctx->f_entropy( ctx->p_entropy, seed + seedlen, nonce_len ) )
Gilles Peskine9be50982019-10-22 18:42:27 +0200371 {
372 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
373 }
374 seedlen += nonce_len;
375 }
376
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200377 /* Add additional data if provided. */
378 if( additional != NULL && len != 0 )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000379 {
380 memcpy( seed + seedlen, additional, len );
381 seedlen += len;
382 }
383
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200384 /* Reduce to 384 bits. */
Dvir Markovich1b364992017-06-26 13:43:34 +0300385 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200386 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000387
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200388 /* Update state. */
Dvir Markovich1b364992017-06-26 13:43:34 +0300389 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200390 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000391 ctx->reseed_counter = 1;
392
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200393exit:
394 mbedtls_platform_zeroize( seed, sizeof( seed ) );
395 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000396}
Paul Bakker9af723c2014-05-01 13:03:14 +0200397
Gilles Peskine9be50982019-10-22 18:42:27 +0200398int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
399 const unsigned char *additional, size_t len )
400{
401 return( mbedtls_ctr_drbg_reseed_internal( ctx, additional, len, 0 ) );
402}
403
Gilles Peskinee9a34542019-10-22 20:43:24 +0200404/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
405 * is sufficient to achieve the maximum security strength given the key
406 * size and entropy length. If there is enough entropy in the initial
407 * call to the entropy function to serve as both the entropy input and
408 * the nonce, don't make a second call to get a nonce. */
409static size_t good_nonce_len( size_t entropy_len )
410{
411 if( entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 )
412 return( 0 );
413 else
414 return( ( entropy_len + 1 ) / 2 );
415}
416
Gilles Peskine8bf56132019-10-02 20:31:54 +0200417/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
Gilles Peskine379561f2019-10-18 16:57:48 +0200418 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
Gilles Peskine8bf56132019-10-02 20:31:54 +0200419 * implements
420 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
421 * security_strength) -> initial_working_state
422 * with inputs
423 * custom[:len] = nonce || personalization_string
Gilles Peskine379561f2019-10-18 16:57:48 +0200424 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
Gilles Peskine8bf56132019-10-02 20:31:54 +0200425 * and with outputs
426 * ctx = initial_working_state
427 */
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200428int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
429 int (*f_entropy)(void *, unsigned char *, size_t),
430 void *p_entropy,
431 const unsigned char *custom,
432 size_t len )
Gilles Peskine8bf56132019-10-02 20:31:54 +0200433{
Janos Follath24eed8d2019-11-22 13:21:35 +0000434 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200435 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Gilles Peskinee9a34542019-10-22 20:43:24 +0200436 size_t nonce_len;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200437
438 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
439
Gilles Peskineda290f92021-02-09 18:44:02 +0100440 /* The mutex is initialized iff f_entropy is set. */
Gilles Peskinef4b34292021-01-30 13:05:32 +0100441#if defined(MBEDTLS_THREADING_C)
442 mbedtls_mutex_init( &ctx->mutex );
443#endif
444
Gilles Peskine8bf56132019-10-02 20:31:54 +0200445 ctx->f_entropy = f_entropy;
446 ctx->p_entropy = p_entropy;
447
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200448 if( ctx->entropy_len == 0 )
449 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskinee9a34542019-10-22 20:43:24 +0200450 /* ctx->reseed_counter contains the desired amount of entropy to
451 * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
452 * If it's -1, indicating that the entropy nonce length was not set
453 * explicitly, use a sufficiently large nonce for security. */
454 nonce_len = ( ctx->reseed_counter >= 0 ?
455 (size_t) ctx->reseed_counter :
456 good_nonce_len( ctx->entropy_len ) );
457
Gilles Peskine9be50982019-10-22 18:42:27 +0200458 /* Initialize with an empty key. */
Gilles Peskine8bf56132019-10-02 20:31:54 +0200459 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
460 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
461 {
462 return( ret );
463 }
464
Gilles Peskinee9a34542019-10-22 20:43:24 +0200465 /* Do the initial seeding. */
Gilles Peskine9be50982019-10-22 18:42:27 +0200466 if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len,
Gilles Peskinee9a34542019-10-22 20:43:24 +0200467 nonce_len ) ) != 0 )
Gilles Peskine8bf56132019-10-02 20:31:54 +0200468 {
469 return( ret );
470 }
471 return( 0 );
472}
473
Gilles Peskineed7da592018-08-03 20:16:52 +0200474/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
475 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
476 * implements
477 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
478 * -> working_state_after_reseed
479 * if required, then
480 * CTR_DRBG_Generate(working_state_after_reseed,
481 * requested_number_of_bits, additional_input)
482 * -> status, returned_bits, new_working_state
483 * with inputs
484 * ctx contains working_state
485 * requested_number_of_bits = 8 * output_len
486 * additional[:add_len] = additional_input
487 * and entropy_input comes from calling ctx->f_entropy
488 * and with outputs
489 * status = SUCCESS (this function does the reseed internally)
490 * returned_bits = output[:output_len]
491 * ctx contains new_working_state
492 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200493int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000494 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000495 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000496{
497 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200498 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
499 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000500 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200501 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000502 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000503 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000504
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200505 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
506 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000507
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200508 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
509 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000510
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200511 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000512
513 if( ctx->reseed_counter > ctx->reseed_interval ||
514 ctx->prediction_resistance )
515 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200516 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300517 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000518 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300519 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000520 add_len = 0;
521 }
522
523 if( add_len > 0 )
524 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300525 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200526 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300527 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200528 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000529 }
530
531 while( output_len > 0 )
532 {
533 /*
534 * Increase counter
535 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200536 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000537 if( ++ctx->counter[i - 1] != 0 )
538 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000539
540 /*
541 * Crypt counter block
542 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100543 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
544 ctx->counter, tmp ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300545 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200546 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300547 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000548
Hanno Beckera08651f2018-10-05 09:38:59 +0100549 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE )
550 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000551 /*
552 * Copy random block to destination
553 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000554 memcpy( p, tmp, use_len );
555 p += use_len;
556 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000557 }
558
Dvir Markovich1b364992017-06-26 13:43:34 +0300559 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200560 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000561
562 ctx->reseed_counter++;
563
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200564exit:
565 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
566 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
Gilles Peskineafaee1c2019-11-28 09:45:32 +0100567 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000568}
569
Hanno Beckera08651f2018-10-05 09:38:59 +0100570int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output,
571 size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000572{
Janos Follath24eed8d2019-11-22 13:21:35 +0000573 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100574 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
575
576#if defined(MBEDTLS_THREADING_C)
577 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
578 return( ret );
579#endif
580
581 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
582
583#if defined(MBEDTLS_THREADING_C)
584 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
585 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
586#endif
587
588 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000589}
590
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200591#if defined(MBEDTLS_FS_IO)
Hanno Beckera08651f2018-10-05 09:38:59 +0100592int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx,
593 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000594{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200595 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000596 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200597 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000598
599 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200600 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000601
Gilles Peskineda0913b2022-06-30 17:03:40 +0200602 /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
603 mbedtls_setbuf( f, NULL );
604
Hanno Beckera08651f2018-10-05 09:38:59 +0100605 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf,
606 MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200607 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000608
Hanno Beckera08651f2018-10-05 09:38:59 +0100609 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) !=
610 MBEDTLS_CTR_DRBG_MAX_INPUT )
611 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200612 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Hanno Beckera08651f2018-10-05 09:38:59 +0100613 }
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100614 else
Hanno Beckera08651f2018-10-05 09:38:59 +0100615 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100616 ret = 0;
Hanno Beckera08651f2018-10-05 09:38:59 +0100617 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000618
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100619exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500620 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200621
Paul Bakkerfc754a92011-12-05 13:23:51 +0000622 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200623 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000624}
625
Hanno Beckera08651f2018-10-05 09:38:59 +0100626int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx,
627 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000628{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100629 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200630 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000631 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200632 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200633 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000634
635 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200636 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000637
Gilles Peskineda0913b2022-06-30 17:03:40 +0200638 /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
639 mbedtls_setbuf( f, NULL );
640
Gilles Peskine82204662018-09-11 18:43:09 +0200641 n = fread( buf, 1, sizeof( buf ), f );
642 if( fread( &c, 1, 1, f ) != 0 )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100643 {
Gilles Peskine82204662018-09-11 18:43:09 +0200644 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
645 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100646 }
Gilles Peskine82204662018-09-11 18:43:09 +0200647 if( n == 0 || ferror( f ) )
648 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100649 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200650 goto exit;
651 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000652 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200653 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200654
TRodziewicz26371e42021-06-08 16:45:41 +0200655 ret = mbedtls_ctr_drbg_update( ctx, buf, n );
Gilles Peskine82204662018-09-11 18:43:09 +0200656
657exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500658 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200659 if( f != NULL )
660 fclose( f );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100661 if( ret != 0 )
662 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200663 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000664}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200665#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000666
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200667#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000668
ENT\stroej170f63d02020-12-28 08:50:23 -0600669/* The CTR_DRBG NIST test vectors used here are available at
670 * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip
671 *
672 * The parameters used to derive the test data are:
673 *
674 * [AES-128 use df]
675 * [PredictionResistance = True/False]
676 * [EntropyInputLen = 128]
677 * [NonceLen = 64]
678 * [PersonalizationStringLen = 128]
679 * [AdditionalInputLen = 0]
680 * [ReturnedBitsLen = 512]
681 *
682 * [AES-256 use df]
683 * [PredictionResistance = True/False]
684 * [EntropyInputLen = 256]
685 * [NonceLen = 128]
686 * [PersonalizationStringLen = 256]
687 * [AdditionalInputLen = 0]
688 * [ReturnedBitsLen = 512]
689 *
690 */
691
Gilles Peskine02e79a42019-10-07 17:06:06 +0200692#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
ENT\stroej1df307002020-12-26 12:41:04 -0600693static const unsigned char entropy_source_pr[] =
694 { 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb,
695 0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92,
696 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8,
697 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20,
698 0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0,
699 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad,
700 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200701
ENT\stroej1df307002020-12-26 12:41:04 -0600702static const unsigned char entropy_source_nopr[] =
703 { 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45,
704 0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9,
705 0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20,
706 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f,
707 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c };
708
stroebeljcd4de1b52021-01-04 18:14:32 -0600709static const unsigned char pers_pr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600710 { 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a,
711 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad };
712
stroebeljcd4de1b52021-01-04 18:14:32 -0600713static const unsigned char pers_nopr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600714 { 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c,
715 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f };
716
717static const unsigned char result_pr[] =
718 { 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66,
719 0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff,
720 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10,
721 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30,
722 0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4,
723 0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc,
724 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06,
725 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf };
726
727static const unsigned char result_nopr[] =
728 { 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13,
729 0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0,
730 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf,
731 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2,
732 0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7,
733 0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2,
734 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02,
735 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200736#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000737
ENT\stroej1df307002020-12-26 12:41:04 -0600738static const unsigned char entropy_source_pr[] =
739 { 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49,
740 0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a,
741 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85,
742 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e,
743 0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15,
744 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45,
745 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8,
746 0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c,
747 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3,
748 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce,
749 0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e,
750 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76,
751 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77,
752 0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe };
753
754static const unsigned char entropy_source_nopr[] =
755 { 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d,
756 0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0,
757 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73,
758 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c,
759 0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2,
760 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1,
761 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a,
762 0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb,
763 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a,
764 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 };
765
stroebeljcd4de1b52021-01-04 18:14:32 -0600766static const unsigned char pers_pr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600767 { 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33,
768 0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e,
769 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0,
770 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 };
771
stroebeljcd4de1b52021-01-04 18:14:32 -0600772static const unsigned char pers_nopr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600773 { 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29,
774 0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf,
775 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb,
776 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b };
777
778static const unsigned char result_pr[] =
779 { 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85,
780 0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d,
781 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62,
782 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d,
783 0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb,
784 0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39,
785 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40,
786 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 };
787
788static const unsigned char result_nopr[] =
789 { 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad,
790 0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3,
791 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b,
792 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14,
793 0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54,
794 0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30,
795 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a,
796 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200797#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000798
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100799static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200800static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
801 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000802{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100803 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000804 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100805 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000806 return( 0 );
807}
808
Paul Bakker7dc4c442014-02-01 22:50:26 +0100809#define CHK( c ) if( (c) != 0 ) \
810 { \
811 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200812 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100813 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100814 }
815
bootstrap-prime6dbbf442022-05-17 19:30:44 -0400816#define SELF_TEST_OUTPUT_DISCARD_LENGTH 64
stroebeljcd4de1b52021-01-04 18:14:32 -0600817
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000818/*
819 * Checkup routine
820 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200821int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000822{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200823 mbedtls_ctr_drbg_context ctx;
stroebeljcd4de1b52021-01-04 18:14:32 -0600824 unsigned char buf[ sizeof( result_pr ) ];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000825
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200826 mbedtls_ctr_drbg_init( &ctx );
827
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000828 /*
829 * Based on a NIST CTR_DRBG test vector (PR = True)
830 */
831 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200832 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000833
834 test_offset = 0;
ENT\stroej1df307002020-12-26 12:41:04 -0600835 mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE );
stroebeljcd4de1b52021-01-04 18:14:32 -0600836 mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200837 CHK( mbedtls_ctr_drbg_seed( &ctx,
838 ctr_drbg_self_test_entropy,
839 (void *) entropy_source_pr,
stroebeljcd4de1b52021-01-04 18:14:32 -0600840 pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200841 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
bootstrap-prime6dbbf442022-05-17 19:30:44 -0400842 CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH ) );
stroebeljcd4de1b52021-01-04 18:14:32 -0600843 CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_pr ) ) );
844 CHK( memcmp( buf, result_pr, sizeof( result_pr ) ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000845
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100846 mbedtls_ctr_drbg_free( &ctx );
847
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000848 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200849 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000850
851 /*
852 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
853 */
854 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200855 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000856
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100857 mbedtls_ctr_drbg_init( &ctx );
858
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000859 test_offset = 0;
ENT\stroej1df307002020-12-26 12:41:04 -0600860 mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
stroebeljcd4de1b52021-01-04 18:14:32 -0600861 mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200862 CHK( mbedtls_ctr_drbg_seed( &ctx,
863 ctr_drbg_self_test_entropy,
864 (void *) entropy_source_nopr,
stroebeljcd4de1b52021-01-04 18:14:32 -0600865 pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200866 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
bootstrap-prime6dbbf442022-05-17 19:30:44 -0400867 CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH ) );
stroebeljcd4de1b52021-01-04 18:14:32 -0600868 CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_nopr ) ) );
869 CHK( memcmp( buf, result_nopr, sizeof( result_nopr ) ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000870
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100871 mbedtls_ctr_drbg_free( &ctx );
872
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000873 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200874 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000875
876 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200877 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000878
879 return( 0 );
880}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200881#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000882
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200883#endif /* MBEDTLS_CTR_DRBG_C */