blob: a604ec0761a641209583bf7f222d6954c86ddbfd [file] [log] [blame]
Paul Bakker0e04d0e2011-11-27 14:46:59 +00001/*
2 * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakker0e04d0e2011-11-27 14:46:59 +000018 */
19/*
Paul Sokolovsky8d6d8c82018-02-10 11:11:41 +020020 * The NIST SP 800-90 DRBGs are described in the following publication.
Paul Bakker0e04d0e2011-11-27 14:46:59 +000021 *
22 * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
23 */
24
Gilles Peskinedb09ef62020-06-03 01:43:33 +020025#include "common.h"
Paul Bakker0e04d0e2011-11-27 14:46:59 +000026
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020027#if defined(MBEDTLS_CTR_DRBG_C)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000028
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000029#include "mbedtls/ctr_drbg.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050030#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000031#include "mbedtls/error.h"
Paul Bakker0e04d0e2011-11-27 14:46:59 +000032
Rich Evans00ab4702015-02-06 13:43:58 +000033#include <string.h>
34
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020035#if defined(MBEDTLS_FS_IO)
Paul Bakkerfc754a92011-12-05 13:23:51 +000036#include <stdio.h>
37#endif
38
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020039#if defined(MBEDTLS_SELF_TEST)
40#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000041#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010042#else
Rich Evans00ab4702015-02-06 13:43:58 +000043#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#define mbedtls_printf printf
45#endif /* MBEDTLS_PLATFORM_C */
46#endif /* MBEDTLS_SELF_TEST */
Paul Bakker7dc4c442014-02-01 22:50:26 +010047
Paul Bakker18d32912011-12-10 21:42:49 +000048/*
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020049 * CTR_DRBG context initialization
50 */
51void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
52{
53 memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
Gilles Peskinee9a34542019-10-22 20:43:24 +020054 /* Indicate that the entropy nonce length is not set explicitly.
55 * See mbedtls_ctr_drbg_set_nonce_len(). */
56 ctx->reseed_counter = -1;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010057
Gavin Acquroff6aceb512020-03-01 17:06:11 -080058 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020059}
60
Gavin Acquroff6aceb512020-03-01 17:06:11 -080061/*
62 * This function resets CTR_DRBG context to the state immediately
63 * after initial call of mbedtls_ctr_drbg_init().
64 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020065void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
Paul Bakkerfff03662014-06-18 16:21:25 +020066{
67 if( ctx == NULL )
68 return;
69
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010070#if defined(MBEDTLS_THREADING_C)
Gilles Peskineda290f92021-02-09 18:44:02 +010071 /* The mutex is initialized iff f_entropy is set. */
Gilles Peskinef4b34292021-01-30 13:05:32 +010072 if( ctx->f_entropy != NULL )
73 mbedtls_mutex_free( &ctx->mutex );
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010074#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020075 mbedtls_aes_free( &ctx->aes_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050076 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Gavin Acquroff6aceb512020-03-01 17:06:11 -080077 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
78 ctx->reseed_counter = -1;
Paul Bakkerfff03662014-06-18 16:21:25 +020079}
80
Hanno Beckera08651f2018-10-05 09:38:59 +010081void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx,
82 int resistance )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000083{
84 ctx->prediction_resistance = resistance;
85}
86
Hanno Beckera08651f2018-10-05 09:38:59 +010087void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx,
88 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000089{
90 ctx->entropy_len = len;
91}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +020092
Gilles Peskine9be50982019-10-22 18:42:27 +020093int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx,
94 size_t len )
95{
96 /* If mbedtls_ctr_drbg_seed() has already been called, it's
97 * too late. Return the error code that's closest to making sense. */
98 if( ctx->f_entropy != NULL )
99 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
100
101 if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
102 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
103#if SIZE_MAX > INT_MAX
104 /* This shouldn't be an issue because
105 * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible
106 * configuration, but make sure anyway. */
107 if( len > INT_MAX )
108 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
109#endif
110
111 /* For backward compatibility with Mbed TLS <= 2.19, store the
112 * entropy nonce length in a field that already exists, but isn't
113 * used until after the initial seeding. */
114 /* Due to the capping of len above, the value fits in an int. */
115 ctx->reseed_counter = (int) len;
116 return( 0 );
117}
118
Hanno Beckera08651f2018-10-05 09:38:59 +0100119void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx,
120 int interval )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000121{
122 ctx->reseed_interval = interval;
123}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200124
125static int block_cipher_df( unsigned char *output,
126 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000127{
Hanno Beckera08651f2018-10-05 09:38:59 +0100128 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
129 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200130 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
131 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
132 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100133 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200134 mbedtls_aes_context aes_ctx;
Dvir Markovich1b364992017-06-26 13:43:34 +0300135 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000136
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200137 int i, j;
138 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000139
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200140 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
141 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100142
Hanno Beckera08651f2018-10-05 09:38:59 +0100143 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
144 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200145 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000146
147 /*
148 * Construct IV (16 bytes) and S in buffer
149 * IV = Counter (in 32-bits) padded to 16 with zeroes
150 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
151 * data || 0x80
152 * (Total is padded to a multiple of 16-bytes with zeroes)
153 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200154 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Joe Subbiania651e6f2021-08-23 11:35:25 +0100155 MBEDTLS_PUT_UINT32_BE( data_len, p, 0);
156 p += 4 + 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200157 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000158 memcpy( p, data, data_len );
159 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000160
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200161 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000162
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200163 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000164 key[i] = i;
165
Hanno Beckera08651f2018-10-05 09:38:59 +0100166 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key,
167 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300168 {
169 goto exit;
170 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000171
172 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200173 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000174 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200175 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000176 {
177 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200178 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000179 use_len = buf_len;
180
181 while( use_len > 0 )
182 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200183 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000184 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200185 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
186 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
187 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000188
Hanno Beckera08651f2018-10-05 09:38:59 +0100189 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
190 chain, chain ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300191 {
192 goto exit;
193 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000194 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200195
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200196 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000197
198 /*
199 * Update IV
200 */
201 buf[3]++;
202 }
203
204 /*
205 * Do final encryption with reduced data
206 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100207 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp,
208 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300209 {
210 goto exit;
211 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200212 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000213 p = output;
214
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200215 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000216 {
Hanno Beckera08651f2018-10-05 09:38:59 +0100217 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
218 iv, iv ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300219 {
220 goto exit;
221 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200222 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
223 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000224 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300225exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200226 mbedtls_aes_free( &aes_ctx );
Dvir Markovich1b364992017-06-26 13:43:34 +0300227 /*
228 * tidy up the stack
229 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500230 mbedtls_platform_zeroize( buf, sizeof( buf ) );
231 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
232 mbedtls_platform_zeroize( key, sizeof( key ) );
233 mbedtls_platform_zeroize( chain, sizeof( chain ) );
Dvir Markovich1b364992017-06-26 13:43:34 +0300234 if( 0 != ret )
235 {
236 /*
237 * wipe partial seed from memory
238 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500239 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
Dvir Markovich1b364992017-06-26 13:43:34 +0300240 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200241
Dvir Markovich1b364992017-06-26 13:43:34 +0300242 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000243}
244
Gilles Peskineed7da592018-08-03 20:16:52 +0200245/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
246 * ctr_drbg_update_internal(ctx, provided_data)
247 * implements
248 * CTR_DRBG_Update(provided_data, Key, V)
249 * with inputs and outputs
250 * ctx->aes_ctx = Key
251 * ctx->counter = V
252 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200253static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
Hanno Beckera08651f2018-10-05 09:38:59 +0100254 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000255{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200256 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000257 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000258 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300259 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000260
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200261 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000262
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200263 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000264 {
265 /*
266 * Increase counter
267 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200268 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000269 if( ++ctx->counter[i - 1] != 0 )
270 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000271
272 /*
273 * Crypt counter block
274 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100275 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
276 ctx->counter, p ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300277 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200278 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300279 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000280
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200281 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000282 }
283
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200284 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000285 tmp[i] ^= data[i];
286
287 /*
288 * Update key and counter
289 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100290 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp,
291 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300292 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200293 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300294 }
Hanno Beckera08651f2018-10-05 09:38:59 +0100295 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
296 MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000297
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200298exit:
299 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
300 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000301}
302
Gilles Peskineed7da592018-08-03 20:16:52 +0200303/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
304 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
305 * implements
306 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
307 * security_strength) -> initial_working_state
308 * with inputs
309 * ctx->counter = all-bits-0
310 * ctx->aes_ctx = context from all-bits-0 key
311 * additional[:add_len] = entropy_input || nonce || personalization_string
312 * and with outputs
313 * ctx = initial_working_state
314 */
Gilles Peskined9199932018-09-11 16:41:54 +0200315int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
316 const unsigned char *additional,
317 size_t add_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000318{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200319 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Janos Follath24eed8d2019-11-22 13:21:35 +0000320 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000321
Gilles Peskined9199932018-09-11 16:41:54 +0200322 if( add_len == 0 )
323 return( 0 );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100324
Gilles Peskined9199932018-09-11 16:41:54 +0200325 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
326 goto exit;
327 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
328 goto exit;
329
330exit:
331 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
332 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000333}
334
Gilles Peskined9199932018-09-11 16:41:54 +0200335#if !defined(MBEDTLS_DEPRECATED_REMOVED)
336void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
337 const unsigned char *additional,
338 size_t add_len )
339{
340 /* MAX_INPUT would be more logical here, but we have to match
341 * block_cipher_df()'s limits since we can't propagate errors */
342 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
343 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
344 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
345}
346#endif /* MBEDTLS_DEPRECATED_REMOVED */
347
Gilles Peskineed7da592018-08-03 20:16:52 +0200348/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
Gilles Peskine9be50982019-10-22 18:42:27 +0200349 * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
Gilles Peskineed7da592018-08-03 20:16:52 +0200350 * implements
351 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
352 * -> new_working_state
353 * with inputs
354 * ctx contains working_state
355 * additional[:len] = additional_input
356 * and entropy_input comes from calling ctx->f_entropy
Gilles Peskine9be50982019-10-22 18:42:27 +0200357 * for (ctx->entropy_len + nonce_len) bytes
Gilles Peskineed7da592018-08-03 20:16:52 +0200358 * and with output
359 * ctx contains new_working_state
360 */
Gilles Peskine97f59ab2019-10-22 18:42:27 +0200361static int mbedtls_ctr_drbg_reseed_internal( mbedtls_ctr_drbg_context *ctx,
362 const unsigned char *additional,
363 size_t len,
364 size_t nonce_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000365{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200366 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000367 size_t seedlen = 0;
Janos Follath24eed8d2019-11-22 13:21:35 +0000368 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000369
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200370 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
371 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Gilles Peskine9be50982019-10-22 18:42:27 +0200372 if( nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
373 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
374 if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200375 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000376
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200377 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000378
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200379 /* Gather entropy_len bytes of entropy to seed state. */
380 if( 0 != ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000381 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200382 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000383 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000384 seedlen += ctx->entropy_len;
385
Gilles Peskine9be50982019-10-22 18:42:27 +0200386 /* Gather entropy for a nonce if requested. */
387 if( nonce_len != 0 )
388 {
ENT\stroej14b919862020-12-23 17:28:33 -0600389 if( 0 != ctx->f_entropy( ctx->p_entropy, seed + seedlen, nonce_len ) )
Gilles Peskine9be50982019-10-22 18:42:27 +0200390 {
391 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
392 }
393 seedlen += nonce_len;
394 }
395
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200396 /* Add additional data if provided. */
397 if( additional != NULL && len != 0 )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000398 {
399 memcpy( seed + seedlen, additional, len );
400 seedlen += len;
401 }
402
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200403 /* Reduce to 384 bits. */
Dvir Markovich1b364992017-06-26 13:43:34 +0300404 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200405 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000406
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200407 /* Update state. */
Dvir Markovich1b364992017-06-26 13:43:34 +0300408 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200409 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000410 ctx->reseed_counter = 1;
411
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200412exit:
413 mbedtls_platform_zeroize( seed, sizeof( seed ) );
414 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000415}
Paul Bakker9af723c2014-05-01 13:03:14 +0200416
Gilles Peskine9be50982019-10-22 18:42:27 +0200417int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
418 const unsigned char *additional, size_t len )
419{
420 return( mbedtls_ctr_drbg_reseed_internal( ctx, additional, len, 0 ) );
421}
422
Gilles Peskinee9a34542019-10-22 20:43:24 +0200423/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
424 * is sufficient to achieve the maximum security strength given the key
425 * size and entropy length. If there is enough entropy in the initial
426 * call to the entropy function to serve as both the entropy input and
427 * the nonce, don't make a second call to get a nonce. */
428static size_t good_nonce_len( size_t entropy_len )
429{
430 if( entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 )
431 return( 0 );
432 else
433 return( ( entropy_len + 1 ) / 2 );
434}
435
Gilles Peskine8bf56132019-10-02 20:31:54 +0200436/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
Gilles Peskine379561f2019-10-18 16:57:48 +0200437 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
Gilles Peskine8bf56132019-10-02 20:31:54 +0200438 * implements
439 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
440 * security_strength) -> initial_working_state
441 * with inputs
442 * custom[:len] = nonce || personalization_string
Gilles Peskine379561f2019-10-18 16:57:48 +0200443 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
Gilles Peskine8bf56132019-10-02 20:31:54 +0200444 * and with outputs
445 * ctx = initial_working_state
446 */
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200447int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
448 int (*f_entropy)(void *, unsigned char *, size_t),
449 void *p_entropy,
450 const unsigned char *custom,
451 size_t len )
Gilles Peskine8bf56132019-10-02 20:31:54 +0200452{
Janos Follath24eed8d2019-11-22 13:21:35 +0000453 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200454 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Gilles Peskinee9a34542019-10-22 20:43:24 +0200455 size_t nonce_len;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200456
457 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
458
Gilles Peskineda290f92021-02-09 18:44:02 +0100459 /* The mutex is initialized iff f_entropy is set. */
Gilles Peskinef4b34292021-01-30 13:05:32 +0100460#if defined(MBEDTLS_THREADING_C)
461 mbedtls_mutex_init( &ctx->mutex );
462#endif
463
Gilles Peskine8bf56132019-10-02 20:31:54 +0200464 mbedtls_aes_init( &ctx->aes_ctx );
465
466 ctx->f_entropy = f_entropy;
467 ctx->p_entropy = p_entropy;
468
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200469 if( ctx->entropy_len == 0 )
470 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskinee9a34542019-10-22 20:43:24 +0200471 /* ctx->reseed_counter contains the desired amount of entropy to
472 * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
473 * If it's -1, indicating that the entropy nonce length was not set
474 * explicitly, use a sufficiently large nonce for security. */
475 nonce_len = ( ctx->reseed_counter >= 0 ?
476 (size_t) ctx->reseed_counter :
477 good_nonce_len( ctx->entropy_len ) );
478
Gilles Peskine9be50982019-10-22 18:42:27 +0200479 /* Initialize with an empty key. */
Gilles Peskine8bf56132019-10-02 20:31:54 +0200480 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
481 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
482 {
483 return( ret );
484 }
485
Gilles Peskinee9a34542019-10-22 20:43:24 +0200486 /* Do the initial seeding. */
Gilles Peskine9be50982019-10-22 18:42:27 +0200487 if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len,
Gilles Peskinee9a34542019-10-22 20:43:24 +0200488 nonce_len ) ) != 0 )
Gilles Peskine8bf56132019-10-02 20:31:54 +0200489 {
490 return( ret );
491 }
492 return( 0 );
493}
494
Gilles Peskineed7da592018-08-03 20:16:52 +0200495/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
496 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
497 * implements
498 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
499 * -> working_state_after_reseed
500 * if required, then
501 * CTR_DRBG_Generate(working_state_after_reseed,
502 * requested_number_of_bits, additional_input)
503 * -> status, returned_bits, new_working_state
504 * with inputs
505 * ctx contains working_state
506 * requested_number_of_bits = 8 * output_len
507 * additional[:add_len] = additional_input
508 * and entropy_input comes from calling ctx->f_entropy
509 * and with outputs
510 * status = SUCCESS (this function does the reseed internally)
511 * returned_bits = output[:output_len]
512 * ctx contains new_working_state
513 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200514int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000515 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000516 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000517{
518 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200519 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
520 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000521 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200522 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000523 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000524 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000525
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200526 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
527 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000528
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200529 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
530 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000531
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200532 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000533
534 if( ctx->reseed_counter > ctx->reseed_interval ||
535 ctx->prediction_resistance )
536 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200537 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300538 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000539 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300540 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000541 add_len = 0;
542 }
543
544 if( add_len > 0 )
545 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300546 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200547 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300548 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200549 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000550 }
551
552 while( output_len > 0 )
553 {
554 /*
555 * Increase counter
556 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200557 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000558 if( ++ctx->counter[i - 1] != 0 )
559 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000560
561 /*
562 * Crypt counter block
563 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100564 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
565 ctx->counter, tmp ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300566 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200567 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300568 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000569
Hanno Beckera08651f2018-10-05 09:38:59 +0100570 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE )
571 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000572 /*
573 * Copy random block to destination
574 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000575 memcpy( p, tmp, use_len );
576 p += use_len;
577 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000578 }
579
Dvir Markovich1b364992017-06-26 13:43:34 +0300580 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200581 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000582
583 ctx->reseed_counter++;
584
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200585exit:
586 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
587 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
Gilles Peskineafaee1c2019-11-28 09:45:32 +0100588 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000589}
590
Hanno Beckera08651f2018-10-05 09:38:59 +0100591int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output,
592 size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000593{
Janos Follath24eed8d2019-11-22 13:21:35 +0000594 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100595 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
596
597#if defined(MBEDTLS_THREADING_C)
598 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
599 return( ret );
600#endif
601
602 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
603
604#if defined(MBEDTLS_THREADING_C)
605 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
606 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
607#endif
608
609 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000610}
611
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200612#if defined(MBEDTLS_FS_IO)
Hanno Beckera08651f2018-10-05 09:38:59 +0100613int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx,
614 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000615{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200616 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000617 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200618 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000619
620 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200621 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000622
Hanno Beckera08651f2018-10-05 09:38:59 +0100623 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf,
624 MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200625 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000626
Hanno Beckera08651f2018-10-05 09:38:59 +0100627 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) !=
628 MBEDTLS_CTR_DRBG_MAX_INPUT )
629 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200630 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Hanno Beckera08651f2018-10-05 09:38:59 +0100631 }
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100632 else
Hanno Beckera08651f2018-10-05 09:38:59 +0100633 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100634 ret = 0;
Hanno Beckera08651f2018-10-05 09:38:59 +0100635 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000636
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100637exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500638 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200639
Paul Bakkerfc754a92011-12-05 13:23:51 +0000640 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200641 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000642}
643
Hanno Beckera08651f2018-10-05 09:38:59 +0100644int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx,
645 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000646{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100647 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200648 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000649 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200650 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200651 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000652
653 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200654 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000655
Gilles Peskine82204662018-09-11 18:43:09 +0200656 n = fread( buf, 1, sizeof( buf ), f );
657 if( fread( &c, 1, 1, f ) != 0 )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100658 {
Gilles Peskine82204662018-09-11 18:43:09 +0200659 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
660 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100661 }
Gilles Peskine82204662018-09-11 18:43:09 +0200662 if( n == 0 || ferror( f ) )
663 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100664 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200665 goto exit;
666 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000667 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200668 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200669
Gilles Peskine82204662018-09-11 18:43:09 +0200670 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
671
672exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500673 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200674 if( f != NULL )
675 fclose( f );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100676 if( ret != 0 )
677 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200678 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000679}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200680#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000681
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200682#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000683
ENT\stroej170f63d02020-12-28 08:50:23 -0600684/* The CTR_DRBG NIST test vectors used here are available at
685 * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip
686 *
687 * The parameters used to derive the test data are:
688 *
689 * [AES-128 use df]
690 * [PredictionResistance = True/False]
691 * [EntropyInputLen = 128]
692 * [NonceLen = 64]
693 * [PersonalizationStringLen = 128]
694 * [AdditionalInputLen = 0]
695 * [ReturnedBitsLen = 512]
696 *
697 * [AES-256 use df]
698 * [PredictionResistance = True/False]
699 * [EntropyInputLen = 256]
700 * [NonceLen = 128]
701 * [PersonalizationStringLen = 256]
702 * [AdditionalInputLen = 0]
703 * [ReturnedBitsLen = 512]
704 *
705 */
706
Gilles Peskine02e79a42019-10-07 17:06:06 +0200707#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
ENT\stroej1df307002020-12-26 12:41:04 -0600708static const unsigned char entropy_source_pr[] =
709 { 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb,
710 0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92,
711 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8,
712 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20,
713 0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0,
714 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad,
715 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200716
ENT\stroej1df307002020-12-26 12:41:04 -0600717static const unsigned char entropy_source_nopr[] =
718 { 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45,
719 0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9,
720 0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20,
721 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f,
722 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c };
723
stroebeljcd4de1b52021-01-04 18:14:32 -0600724static const unsigned char pers_pr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600725 { 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a,
726 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad };
727
stroebeljcd4de1b52021-01-04 18:14:32 -0600728static const unsigned char pers_nopr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600729 { 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c,
730 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f };
731
732static const unsigned char result_pr[] =
733 { 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66,
734 0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff,
735 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10,
736 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30,
737 0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4,
738 0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc,
739 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06,
740 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf };
741
742static const unsigned char result_nopr[] =
743 { 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13,
744 0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0,
745 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf,
746 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2,
747 0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7,
748 0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2,
749 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02,
750 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200751#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000752
ENT\stroej1df307002020-12-26 12:41:04 -0600753static const unsigned char entropy_source_pr[] =
754 { 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49,
755 0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a,
756 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85,
757 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e,
758 0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15,
759 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45,
760 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8,
761 0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c,
762 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3,
763 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce,
764 0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e,
765 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76,
766 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77,
767 0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe };
768
769static const unsigned char entropy_source_nopr[] =
770 { 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d,
771 0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0,
772 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73,
773 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c,
774 0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2,
775 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1,
776 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a,
777 0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb,
778 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a,
779 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 };
780
stroebeljcd4de1b52021-01-04 18:14:32 -0600781static const unsigned char pers_pr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600782 { 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33,
783 0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e,
784 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0,
785 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 };
786
stroebeljcd4de1b52021-01-04 18:14:32 -0600787static const unsigned char pers_nopr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600788 { 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29,
789 0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf,
790 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb,
791 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b };
792
793static const unsigned char result_pr[] =
794 { 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85,
795 0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d,
796 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62,
797 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d,
798 0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb,
799 0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39,
800 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40,
801 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 };
802
803static const unsigned char result_nopr[] =
804 { 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad,
805 0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3,
806 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b,
807 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14,
808 0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54,
809 0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30,
810 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a,
811 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200812#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000813
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100814static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200815static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
816 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000817{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100818 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000819 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100820 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000821 return( 0 );
822}
823
Paul Bakker7dc4c442014-02-01 22:50:26 +0100824#define CHK( c ) if( (c) != 0 ) \
825 { \
826 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200827 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100828 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100829 }
830
stroebeljcd4de1b52021-01-04 18:14:32 -0600831#define SELF_TEST_OUPUT_DISCARD_LENGTH 64
832
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000833/*
834 * Checkup routine
835 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200836int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000837{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200838 mbedtls_ctr_drbg_context ctx;
stroebeljcd4de1b52021-01-04 18:14:32 -0600839 unsigned char buf[ sizeof( result_pr ) ];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000840
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200841 mbedtls_ctr_drbg_init( &ctx );
842
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000843 /*
844 * Based on a NIST CTR_DRBG test vector (PR = True)
845 */
846 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200847 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000848
849 test_offset = 0;
ENT\stroej1df307002020-12-26 12:41:04 -0600850 mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE );
stroebeljcd4de1b52021-01-04 18:14:32 -0600851 mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200852 CHK( mbedtls_ctr_drbg_seed( &ctx,
853 ctr_drbg_self_test_entropy,
854 (void *) entropy_source_pr,
stroebeljcd4de1b52021-01-04 18:14:32 -0600855 pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200856 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
stroebeljcd4de1b52021-01-04 18:14:32 -0600857 CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUPUT_DISCARD_LENGTH ) );
858 CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_pr ) ) );
859 CHK( memcmp( buf, result_pr, sizeof( result_pr ) ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000860
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100861 mbedtls_ctr_drbg_free( &ctx );
862
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000863 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200864 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000865
866 /*
867 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
868 */
869 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200870 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000871
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100872 mbedtls_ctr_drbg_init( &ctx );
873
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000874 test_offset = 0;
ENT\stroej1df307002020-12-26 12:41:04 -0600875 mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
stroebeljcd4de1b52021-01-04 18:14:32 -0600876 mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200877 CHK( mbedtls_ctr_drbg_seed( &ctx,
878 ctr_drbg_self_test_entropy,
879 (void *) entropy_source_nopr,
stroebeljcd4de1b52021-01-04 18:14:32 -0600880 pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200881 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
stroebeljcd4de1b52021-01-04 18:14:32 -0600882 CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUPUT_DISCARD_LENGTH ) );
883 CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_nopr ) ) );
884 CHK( memcmp( buf, result_nopr, sizeof( result_nopr ) ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000885
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100886 mbedtls_ctr_drbg_free( &ctx );
887
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000888 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200889 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000890
891 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200892 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000893
894 return( 0 );
895}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200896#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000897
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200898#endif /* MBEDTLS_CTR_DRBG_C */