blob: a2f55cc5944eb97f2e1fbfdbc85f2696bac1c1ea [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 Subbiania5cb0d22021-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)
TRodziewicz26371e42021-06-08 16:45:41 +0200304 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
Gilles Peskineed7da592018-08-03 20:16:52 +0200305 * 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 */
TRodziewicz26371e42021-06-08 16:45:41 +0200315int mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
Gilles Peskined9199932018-09-11 16:41:54 +0200316 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 Peskineed7da592018-08-03 20:16:52 +0200335/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
Gilles Peskine9be50982019-10-22 18:42:27 +0200336 * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
Gilles Peskineed7da592018-08-03 20:16:52 +0200337 * implements
338 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
339 * -> new_working_state
340 * with inputs
341 * ctx contains working_state
342 * additional[:len] = additional_input
343 * and entropy_input comes from calling ctx->f_entropy
Gilles Peskine9be50982019-10-22 18:42:27 +0200344 * for (ctx->entropy_len + nonce_len) bytes
Gilles Peskineed7da592018-08-03 20:16:52 +0200345 * and with output
346 * ctx contains new_working_state
347 */
Gilles Peskine97f59ab2019-10-22 18:42:27 +0200348static int mbedtls_ctr_drbg_reseed_internal( mbedtls_ctr_drbg_context *ctx,
349 const unsigned char *additional,
350 size_t len,
351 size_t nonce_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000352{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200353 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000354 size_t seedlen = 0;
Janos Follath24eed8d2019-11-22 13:21:35 +0000355 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000356
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200357 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
358 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Gilles Peskine9be50982019-10-22 18:42:27 +0200359 if( nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
360 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
361 if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200362 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000363
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200364 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000365
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200366 /* Gather entropy_len bytes of entropy to seed state. */
367 if( 0 != ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000368 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200369 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000370 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000371 seedlen += ctx->entropy_len;
372
Gilles Peskine9be50982019-10-22 18:42:27 +0200373 /* Gather entropy for a nonce if requested. */
374 if( nonce_len != 0 )
375 {
ENT\stroej14b919862020-12-23 17:28:33 -0600376 if( 0 != ctx->f_entropy( ctx->p_entropy, seed + seedlen, nonce_len ) )
Gilles Peskine9be50982019-10-22 18:42:27 +0200377 {
378 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
379 }
380 seedlen += nonce_len;
381 }
382
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200383 /* Add additional data if provided. */
384 if( additional != NULL && len != 0 )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000385 {
386 memcpy( seed + seedlen, additional, len );
387 seedlen += len;
388 }
389
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200390 /* Reduce to 384 bits. */
Dvir Markovich1b364992017-06-26 13:43:34 +0300391 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200392 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000393
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200394 /* Update state. */
Dvir Markovich1b364992017-06-26 13:43:34 +0300395 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200396 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000397 ctx->reseed_counter = 1;
398
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200399exit:
400 mbedtls_platform_zeroize( seed, sizeof( seed ) );
401 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000402}
Paul Bakker9af723c2014-05-01 13:03:14 +0200403
Gilles Peskine9be50982019-10-22 18:42:27 +0200404int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
405 const unsigned char *additional, size_t len )
406{
407 return( mbedtls_ctr_drbg_reseed_internal( ctx, additional, len, 0 ) );
408}
409
Gilles Peskinee9a34542019-10-22 20:43:24 +0200410/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
411 * is sufficient to achieve the maximum security strength given the key
412 * size and entropy length. If there is enough entropy in the initial
413 * call to the entropy function to serve as both the entropy input and
414 * the nonce, don't make a second call to get a nonce. */
415static size_t good_nonce_len( size_t entropy_len )
416{
417 if( entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 )
418 return( 0 );
419 else
420 return( ( entropy_len + 1 ) / 2 );
421}
422
Gilles Peskine8bf56132019-10-02 20:31:54 +0200423/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
Gilles Peskine379561f2019-10-18 16:57:48 +0200424 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
Gilles Peskine8bf56132019-10-02 20:31:54 +0200425 * implements
426 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
427 * security_strength) -> initial_working_state
428 * with inputs
429 * custom[:len] = nonce || personalization_string
Gilles Peskine379561f2019-10-18 16:57:48 +0200430 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
Gilles Peskine8bf56132019-10-02 20:31:54 +0200431 * and with outputs
432 * ctx = initial_working_state
433 */
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200434int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
435 int (*f_entropy)(void *, unsigned char *, size_t),
436 void *p_entropy,
437 const unsigned char *custom,
438 size_t len )
Gilles Peskine8bf56132019-10-02 20:31:54 +0200439{
Janos Follath24eed8d2019-11-22 13:21:35 +0000440 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200441 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Gilles Peskinee9a34542019-10-22 20:43:24 +0200442 size_t nonce_len;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200443
444 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
445
Gilles Peskineda290f92021-02-09 18:44:02 +0100446 /* The mutex is initialized iff f_entropy is set. */
Gilles Peskinef4b34292021-01-30 13:05:32 +0100447#if defined(MBEDTLS_THREADING_C)
448 mbedtls_mutex_init( &ctx->mutex );
449#endif
450
Gilles Peskine8bf56132019-10-02 20:31:54 +0200451 mbedtls_aes_init( &ctx->aes_ctx );
452
453 ctx->f_entropy = f_entropy;
454 ctx->p_entropy = p_entropy;
455
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200456 if( ctx->entropy_len == 0 )
457 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskinee9a34542019-10-22 20:43:24 +0200458 /* ctx->reseed_counter contains the desired amount of entropy to
459 * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
460 * If it's -1, indicating that the entropy nonce length was not set
461 * explicitly, use a sufficiently large nonce for security. */
462 nonce_len = ( ctx->reseed_counter >= 0 ?
463 (size_t) ctx->reseed_counter :
464 good_nonce_len( ctx->entropy_len ) );
465
Gilles Peskine9be50982019-10-22 18:42:27 +0200466 /* Initialize with an empty key. */
Gilles Peskine8bf56132019-10-02 20:31:54 +0200467 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
468 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
469 {
470 return( ret );
471 }
472
Gilles Peskinee9a34542019-10-22 20:43:24 +0200473 /* Do the initial seeding. */
Gilles Peskine9be50982019-10-22 18:42:27 +0200474 if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len,
Gilles Peskinee9a34542019-10-22 20:43:24 +0200475 nonce_len ) ) != 0 )
Gilles Peskine8bf56132019-10-02 20:31:54 +0200476 {
477 return( ret );
478 }
479 return( 0 );
480}
481
Gilles Peskineed7da592018-08-03 20:16:52 +0200482/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
483 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
484 * implements
485 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
486 * -> working_state_after_reseed
487 * if required, then
488 * CTR_DRBG_Generate(working_state_after_reseed,
489 * requested_number_of_bits, additional_input)
490 * -> status, returned_bits, new_working_state
491 * with inputs
492 * ctx contains working_state
493 * requested_number_of_bits = 8 * output_len
494 * additional[:add_len] = additional_input
495 * and entropy_input comes from calling ctx->f_entropy
496 * and with outputs
497 * status = SUCCESS (this function does the reseed internally)
498 * returned_bits = output[:output_len]
499 * ctx contains new_working_state
500 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200501int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000502 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000503 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000504{
505 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200506 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
507 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000508 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200509 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000510 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000511 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000512
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200513 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
514 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000515
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200516 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
517 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000518
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200519 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000520
521 if( ctx->reseed_counter > ctx->reseed_interval ||
522 ctx->prediction_resistance )
523 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200524 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300525 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000526 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300527 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000528 add_len = 0;
529 }
530
531 if( add_len > 0 )
532 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300533 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200534 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300535 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200536 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000537 }
538
539 while( output_len > 0 )
540 {
541 /*
542 * Increase counter
543 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200544 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000545 if( ++ctx->counter[i - 1] != 0 )
546 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000547
548 /*
549 * Crypt counter block
550 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100551 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
552 ctx->counter, tmp ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300553 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200554 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300555 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000556
Hanno Beckera08651f2018-10-05 09:38:59 +0100557 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE )
558 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000559 /*
560 * Copy random block to destination
561 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000562 memcpy( p, tmp, use_len );
563 p += use_len;
564 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000565 }
566
Dvir Markovich1b364992017-06-26 13:43:34 +0300567 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200568 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000569
570 ctx->reseed_counter++;
571
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200572exit:
573 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
574 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
Gilles Peskineafaee1c2019-11-28 09:45:32 +0100575 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000576}
577
Hanno Beckera08651f2018-10-05 09:38:59 +0100578int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output,
579 size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000580{
Janos Follath24eed8d2019-11-22 13:21:35 +0000581 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100582 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
583
584#if defined(MBEDTLS_THREADING_C)
585 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
586 return( ret );
587#endif
588
589 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
590
591#if defined(MBEDTLS_THREADING_C)
592 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
593 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
594#endif
595
596 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000597}
598
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200599#if defined(MBEDTLS_FS_IO)
Hanno Beckera08651f2018-10-05 09:38:59 +0100600int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx,
601 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000602{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200603 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000604 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200605 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000606
607 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200608 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000609
Gilles Peskineda0913b2022-06-30 17:03:40 +0200610 /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
611 mbedtls_setbuf( f, NULL );
612
Hanno Beckera08651f2018-10-05 09:38:59 +0100613 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf,
614 MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200615 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000616
Hanno Beckera08651f2018-10-05 09:38:59 +0100617 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) !=
618 MBEDTLS_CTR_DRBG_MAX_INPUT )
619 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200620 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Hanno Beckera08651f2018-10-05 09:38:59 +0100621 }
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100622 else
Hanno Beckera08651f2018-10-05 09:38:59 +0100623 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100624 ret = 0;
Hanno Beckera08651f2018-10-05 09:38:59 +0100625 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000626
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100627exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500628 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200629
Paul Bakkerfc754a92011-12-05 13:23:51 +0000630 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200631 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000632}
633
Hanno Beckera08651f2018-10-05 09:38:59 +0100634int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx,
635 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000636{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100637 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200638 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000639 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200640 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200641 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000642
643 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200644 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000645
Gilles Peskineda0913b2022-06-30 17:03:40 +0200646 /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
647 mbedtls_setbuf( f, NULL );
648
Gilles Peskine82204662018-09-11 18:43:09 +0200649 n = fread( buf, 1, sizeof( buf ), f );
650 if( fread( &c, 1, 1, f ) != 0 )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100651 {
Gilles Peskine82204662018-09-11 18:43:09 +0200652 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
653 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100654 }
Gilles Peskine82204662018-09-11 18:43:09 +0200655 if( n == 0 || ferror( f ) )
656 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100657 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200658 goto exit;
659 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000660 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200661 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200662
TRodziewicz26371e42021-06-08 16:45:41 +0200663 ret = mbedtls_ctr_drbg_update( ctx, buf, n );
Gilles Peskine82204662018-09-11 18:43:09 +0200664
665exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500666 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200667 if( f != NULL )
668 fclose( f );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100669 if( ret != 0 )
670 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200671 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000672}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200673#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000674
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200675#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000676
ENT\stroej170f63d02020-12-28 08:50:23 -0600677/* The CTR_DRBG NIST test vectors used here are available at
678 * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip
679 *
680 * The parameters used to derive the test data are:
681 *
682 * [AES-128 use df]
683 * [PredictionResistance = True/False]
684 * [EntropyInputLen = 128]
685 * [NonceLen = 64]
686 * [PersonalizationStringLen = 128]
687 * [AdditionalInputLen = 0]
688 * [ReturnedBitsLen = 512]
689 *
690 * [AES-256 use df]
691 * [PredictionResistance = True/False]
692 * [EntropyInputLen = 256]
693 * [NonceLen = 128]
694 * [PersonalizationStringLen = 256]
695 * [AdditionalInputLen = 0]
696 * [ReturnedBitsLen = 512]
697 *
698 */
699
Gilles Peskine02e79a42019-10-07 17:06:06 +0200700#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
ENT\stroej1df307002020-12-26 12:41:04 -0600701static const unsigned char entropy_source_pr[] =
702 { 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb,
703 0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92,
704 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8,
705 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20,
706 0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0,
707 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad,
708 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200709
ENT\stroej1df307002020-12-26 12:41:04 -0600710static const unsigned char entropy_source_nopr[] =
711 { 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45,
712 0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9,
713 0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20,
714 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f,
715 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c };
716
stroebeljcd4de1b52021-01-04 18:14:32 -0600717static const unsigned char pers_pr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600718 { 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a,
719 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad };
720
stroebeljcd4de1b52021-01-04 18:14:32 -0600721static const unsigned char pers_nopr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600722 { 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c,
723 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f };
724
725static const unsigned char result_pr[] =
726 { 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66,
727 0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff,
728 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10,
729 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30,
730 0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4,
731 0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc,
732 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06,
733 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf };
734
735static const unsigned char result_nopr[] =
736 { 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13,
737 0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0,
738 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf,
739 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2,
740 0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7,
741 0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2,
742 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02,
743 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200744#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000745
ENT\stroej1df307002020-12-26 12:41:04 -0600746static const unsigned char entropy_source_pr[] =
747 { 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49,
748 0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a,
749 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85,
750 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e,
751 0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15,
752 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45,
753 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8,
754 0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c,
755 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3,
756 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce,
757 0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e,
758 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76,
759 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77,
760 0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe };
761
762static const unsigned char entropy_source_nopr[] =
763 { 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d,
764 0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0,
765 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73,
766 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c,
767 0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2,
768 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1,
769 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a,
770 0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb,
771 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a,
772 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 };
773
stroebeljcd4de1b52021-01-04 18:14:32 -0600774static const unsigned char pers_pr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600775 { 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33,
776 0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e,
777 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0,
778 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 };
779
stroebeljcd4de1b52021-01-04 18:14:32 -0600780static const unsigned char pers_nopr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600781 { 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29,
782 0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf,
783 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb,
784 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b };
785
786static const unsigned char result_pr[] =
787 { 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85,
788 0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d,
789 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62,
790 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d,
791 0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb,
792 0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39,
793 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40,
794 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 };
795
796static const unsigned char result_nopr[] =
797 { 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad,
798 0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3,
799 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b,
800 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14,
801 0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54,
802 0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30,
803 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a,
804 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200805#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000806
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100807static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200808static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
809 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000810{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100811 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000812 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100813 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000814 return( 0 );
815}
816
Paul Bakker7dc4c442014-02-01 22:50:26 +0100817#define CHK( c ) if( (c) != 0 ) \
818 { \
819 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200820 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100821 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100822 }
823
stroebeljcd4de1b52021-01-04 18:14:32 -0600824#define SELF_TEST_OUPUT_DISCARD_LENGTH 64
825
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000826/*
827 * Checkup routine
828 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200829int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000830{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200831 mbedtls_ctr_drbg_context ctx;
stroebeljcd4de1b52021-01-04 18:14:32 -0600832 unsigned char buf[ sizeof( result_pr ) ];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000833
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200834 mbedtls_ctr_drbg_init( &ctx );
835
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000836 /*
837 * Based on a NIST CTR_DRBG test vector (PR = True)
838 */
839 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200840 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000841
842 test_offset = 0;
ENT\stroej1df307002020-12-26 12:41:04 -0600843 mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE );
stroebeljcd4de1b52021-01-04 18:14:32 -0600844 mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200845 CHK( mbedtls_ctr_drbg_seed( &ctx,
846 ctr_drbg_self_test_entropy,
847 (void *) entropy_source_pr,
stroebeljcd4de1b52021-01-04 18:14:32 -0600848 pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200849 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
stroebeljcd4de1b52021-01-04 18:14:32 -0600850 CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUPUT_DISCARD_LENGTH ) );
851 CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_pr ) ) );
852 CHK( memcmp( buf, result_pr, sizeof( result_pr ) ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000853
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100854 mbedtls_ctr_drbg_free( &ctx );
855
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000856 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200857 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000858
859 /*
860 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
861 */
862 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200863 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000864
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100865 mbedtls_ctr_drbg_init( &ctx );
866
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000867 test_offset = 0;
ENT\stroej1df307002020-12-26 12:41:04 -0600868 mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
stroebeljcd4de1b52021-01-04 18:14:32 -0600869 mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200870 CHK( mbedtls_ctr_drbg_seed( &ctx,
871 ctr_drbg_self_test_entropy,
872 (void *) entropy_source_nopr,
stroebeljcd4de1b52021-01-04 18:14:32 -0600873 pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200874 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
stroebeljcd4de1b52021-01-04 18:14:32 -0600875 CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUPUT_DISCARD_LENGTH ) );
876 CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_nopr ) ) );
877 CHK( memcmp( buf, result_nopr, sizeof( result_nopr ) ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000878
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100879 mbedtls_ctr_drbg_free( &ctx );
880
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000881 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200882 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000883
884 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200885 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000886
887 return( 0 );
888}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200889#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000890
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200891#endif /* MBEDTLS_CTR_DRBG_C */