blob: 602ec699c4eced89048aac2576ca7b13bf542d2d [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;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000155 *p++ = ( data_len >> 24 ) & 0xff;
156 *p++ = ( data_len >> 16 ) & 0xff;
157 *p++ = ( data_len >> 8 ) & 0xff;
158 *p++ = ( data_len ) & 0xff;
159 p += 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200160 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000161 memcpy( p, data, data_len );
162 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000163
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200164 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000165
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200166 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000167 key[i] = i;
168
Hanno Beckera08651f2018-10-05 09:38:59 +0100169 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key,
170 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300171 {
172 goto exit;
173 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000174
175 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200176 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000177 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200178 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000179 {
180 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200181 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000182 use_len = buf_len;
183
184 while( use_len > 0 )
185 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200186 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000187 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200188 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
189 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
190 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000191
Hanno Beckera08651f2018-10-05 09:38:59 +0100192 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
193 chain, chain ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300194 {
195 goto exit;
196 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000197 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200198
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200199 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000200
201 /*
202 * Update IV
203 */
204 buf[3]++;
205 }
206
207 /*
208 * Do final encryption with reduced data
209 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100210 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp,
211 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300212 {
213 goto exit;
214 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200215 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000216 p = output;
217
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200218 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000219 {
Hanno Beckera08651f2018-10-05 09:38:59 +0100220 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
221 iv, iv ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300222 {
223 goto exit;
224 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200225 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
226 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000227 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300228exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200229 mbedtls_aes_free( &aes_ctx );
Dvir Markovich1b364992017-06-26 13:43:34 +0300230 /*
231 * tidy up the stack
232 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500233 mbedtls_platform_zeroize( buf, sizeof( buf ) );
234 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
235 mbedtls_platform_zeroize( key, sizeof( key ) );
236 mbedtls_platform_zeroize( chain, sizeof( chain ) );
Dvir Markovich1b364992017-06-26 13:43:34 +0300237 if( 0 != ret )
238 {
239 /*
240 * wipe partial seed from memory
241 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500242 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
Dvir Markovich1b364992017-06-26 13:43:34 +0300243 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200244
Dvir Markovich1b364992017-06-26 13:43:34 +0300245 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000246}
247
Gilles Peskineed7da592018-08-03 20:16:52 +0200248/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
249 * ctr_drbg_update_internal(ctx, provided_data)
250 * implements
251 * CTR_DRBG_Update(provided_data, Key, V)
252 * with inputs and outputs
253 * ctx->aes_ctx = Key
254 * ctx->counter = V
255 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200256static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
Hanno Beckera08651f2018-10-05 09:38:59 +0100257 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000258{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200259 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000260 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000261 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300262 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000263
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200264 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000265
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200266 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000267 {
268 /*
269 * Increase counter
270 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200271 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000272 if( ++ctx->counter[i - 1] != 0 )
273 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000274
275 /*
276 * Crypt counter block
277 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100278 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
279 ctx->counter, p ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300280 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200281 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300282 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000283
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200284 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000285 }
286
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200287 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000288 tmp[i] ^= data[i];
289
290 /*
291 * Update key and counter
292 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100293 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp,
294 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300295 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200296 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300297 }
Hanno Beckera08651f2018-10-05 09:38:59 +0100298 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
299 MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000300
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200301exit:
302 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
303 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000304}
305
Gilles Peskineed7da592018-08-03 20:16:52 +0200306/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
TRodziewicz18efb732021-04-29 23:12:19 +0200307 * mbedtls_ctr_drbg_update_ret(ctx, additional, add_len)
Gilles Peskineed7da592018-08-03 20:16:52 +0200308 * implements
309 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
310 * security_strength) -> initial_working_state
311 * with inputs
312 * ctx->counter = all-bits-0
313 * ctx->aes_ctx = context from all-bits-0 key
314 * additional[:add_len] = entropy_input || nonce || personalization_string
315 * and with outputs
316 * ctx = initial_working_state
317 */
Gilles Peskined9199932018-09-11 16:41:54 +0200318int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
319 const unsigned char *additional,
320 size_t add_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000321{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200322 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Janos Follath24eed8d2019-11-22 13:21:35 +0000323 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000324
Gilles Peskined9199932018-09-11 16:41:54 +0200325 if( add_len == 0 )
326 return( 0 );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100327
Gilles Peskined9199932018-09-11 16:41:54 +0200328 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
329 goto exit;
330 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
331 goto exit;
332
333exit:
334 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
335 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000336}
337
Gilles Peskineed7da592018-08-03 20:16:52 +0200338/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
Gilles Peskine9be50982019-10-22 18:42:27 +0200339 * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
Gilles Peskineed7da592018-08-03 20:16:52 +0200340 * implements
341 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
342 * -> new_working_state
343 * with inputs
344 * ctx contains working_state
345 * additional[:len] = additional_input
346 * and entropy_input comes from calling ctx->f_entropy
Gilles Peskine9be50982019-10-22 18:42:27 +0200347 * for (ctx->entropy_len + nonce_len) bytes
Gilles Peskineed7da592018-08-03 20:16:52 +0200348 * and with output
349 * ctx contains new_working_state
350 */
Gilles Peskine97f59ab2019-10-22 18:42:27 +0200351static int mbedtls_ctr_drbg_reseed_internal( mbedtls_ctr_drbg_context *ctx,
352 const unsigned char *additional,
353 size_t len,
354 size_t nonce_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000355{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200356 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000357 size_t seedlen = 0;
Janos Follath24eed8d2019-11-22 13:21:35 +0000358 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000359
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200360 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
361 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Gilles Peskine9be50982019-10-22 18:42:27 +0200362 if( nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
363 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
364 if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200365 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000366
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200367 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000368
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200369 /* Gather entropy_len bytes of entropy to seed state. */
370 if( 0 != ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000371 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200372 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000373 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000374 seedlen += ctx->entropy_len;
375
Gilles Peskine9be50982019-10-22 18:42:27 +0200376 /* Gather entropy for a nonce if requested. */
377 if( nonce_len != 0 )
378 {
ENT\stroej14b919862020-12-23 17:28:33 -0600379 if( 0 != ctx->f_entropy( ctx->p_entropy, seed + seedlen, nonce_len ) )
Gilles Peskine9be50982019-10-22 18:42:27 +0200380 {
381 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
382 }
383 seedlen += nonce_len;
384 }
385
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200386 /* Add additional data if provided. */
387 if( additional != NULL && len != 0 )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000388 {
389 memcpy( seed + seedlen, additional, len );
390 seedlen += len;
391 }
392
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200393 /* Reduce to 384 bits. */
Dvir Markovich1b364992017-06-26 13:43:34 +0300394 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200395 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000396
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200397 /* Update state. */
Dvir Markovich1b364992017-06-26 13:43:34 +0300398 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200399 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000400 ctx->reseed_counter = 1;
401
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200402exit:
403 mbedtls_platform_zeroize( seed, sizeof( seed ) );
404 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000405}
Paul Bakker9af723c2014-05-01 13:03:14 +0200406
Gilles Peskine9be50982019-10-22 18:42:27 +0200407int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
408 const unsigned char *additional, size_t len )
409{
410 return( mbedtls_ctr_drbg_reseed_internal( ctx, additional, len, 0 ) );
411}
412
Gilles Peskinee9a34542019-10-22 20:43:24 +0200413/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
414 * is sufficient to achieve the maximum security strength given the key
415 * size and entropy length. If there is enough entropy in the initial
416 * call to the entropy function to serve as both the entropy input and
417 * the nonce, don't make a second call to get a nonce. */
418static size_t good_nonce_len( size_t entropy_len )
419{
420 if( entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 )
421 return( 0 );
422 else
423 return( ( entropy_len + 1 ) / 2 );
424}
425
Gilles Peskine8bf56132019-10-02 20:31:54 +0200426/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
Gilles Peskine379561f2019-10-18 16:57:48 +0200427 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
Gilles Peskine8bf56132019-10-02 20:31:54 +0200428 * implements
429 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
430 * security_strength) -> initial_working_state
431 * with inputs
432 * custom[:len] = nonce || personalization_string
Gilles Peskine379561f2019-10-18 16:57:48 +0200433 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
Gilles Peskine8bf56132019-10-02 20:31:54 +0200434 * and with outputs
435 * ctx = initial_working_state
436 */
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200437int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
438 int (*f_entropy)(void *, unsigned char *, size_t),
439 void *p_entropy,
440 const unsigned char *custom,
441 size_t len )
Gilles Peskine8bf56132019-10-02 20:31:54 +0200442{
Janos Follath24eed8d2019-11-22 13:21:35 +0000443 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200444 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Gilles Peskinee9a34542019-10-22 20:43:24 +0200445 size_t nonce_len;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200446
447 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
448
Gilles Peskineda290f92021-02-09 18:44:02 +0100449 /* The mutex is initialized iff f_entropy is set. */
Gilles Peskinef4b34292021-01-30 13:05:32 +0100450#if defined(MBEDTLS_THREADING_C)
451 mbedtls_mutex_init( &ctx->mutex );
452#endif
453
Gilles Peskine8bf56132019-10-02 20:31:54 +0200454 mbedtls_aes_init( &ctx->aes_ctx );
455
456 ctx->f_entropy = f_entropy;
457 ctx->p_entropy = p_entropy;
458
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200459 if( ctx->entropy_len == 0 )
460 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskinee9a34542019-10-22 20:43:24 +0200461 /* ctx->reseed_counter contains the desired amount of entropy to
462 * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
463 * If it's -1, indicating that the entropy nonce length was not set
464 * explicitly, use a sufficiently large nonce for security. */
465 nonce_len = ( ctx->reseed_counter >= 0 ?
466 (size_t) ctx->reseed_counter :
467 good_nonce_len( ctx->entropy_len ) );
468
Gilles Peskine9be50982019-10-22 18:42:27 +0200469 /* Initialize with an empty key. */
Gilles Peskine8bf56132019-10-02 20:31:54 +0200470 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
471 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
472 {
473 return( ret );
474 }
475
Gilles Peskinee9a34542019-10-22 20:43:24 +0200476 /* Do the initial seeding. */
Gilles Peskine9be50982019-10-22 18:42:27 +0200477 if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len,
Gilles Peskinee9a34542019-10-22 20:43:24 +0200478 nonce_len ) ) != 0 )
Gilles Peskine8bf56132019-10-02 20:31:54 +0200479 {
480 return( ret );
481 }
482 return( 0 );
483}
484
Gilles Peskineed7da592018-08-03 20:16:52 +0200485/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
486 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
487 * implements
488 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
489 * -> working_state_after_reseed
490 * if required, then
491 * CTR_DRBG_Generate(working_state_after_reseed,
492 * requested_number_of_bits, additional_input)
493 * -> status, returned_bits, new_working_state
494 * with inputs
495 * ctx contains working_state
496 * requested_number_of_bits = 8 * output_len
497 * additional[:add_len] = additional_input
498 * and entropy_input comes from calling ctx->f_entropy
499 * and with outputs
500 * status = SUCCESS (this function does the reseed internally)
501 * returned_bits = output[:output_len]
502 * ctx contains new_working_state
503 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200504int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000505 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000506 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000507{
508 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200509 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
510 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000511 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200512 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000513 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000514 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000515
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200516 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
517 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000518
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200519 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
520 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000521
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200522 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000523
524 if( ctx->reseed_counter > ctx->reseed_interval ||
525 ctx->prediction_resistance )
526 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200527 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300528 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000529 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300530 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000531 add_len = 0;
532 }
533
534 if( add_len > 0 )
535 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300536 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200537 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300538 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200539 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000540 }
541
542 while( output_len > 0 )
543 {
544 /*
545 * Increase counter
546 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200547 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000548 if( ++ctx->counter[i - 1] != 0 )
549 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000550
551 /*
552 * Crypt counter block
553 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100554 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
555 ctx->counter, tmp ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300556 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200557 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300558 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000559
Hanno Beckera08651f2018-10-05 09:38:59 +0100560 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE )
561 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000562 /*
563 * Copy random block to destination
564 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000565 memcpy( p, tmp, use_len );
566 p += use_len;
567 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000568 }
569
Dvir Markovich1b364992017-06-26 13:43:34 +0300570 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200571 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000572
573 ctx->reseed_counter++;
574
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200575exit:
576 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
577 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
Gilles Peskineafaee1c2019-11-28 09:45:32 +0100578 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000579}
580
Hanno Beckera08651f2018-10-05 09:38:59 +0100581int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output,
582 size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000583{
Janos Follath24eed8d2019-11-22 13:21:35 +0000584 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100585 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
586
587#if defined(MBEDTLS_THREADING_C)
588 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
589 return( ret );
590#endif
591
592 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
593
594#if defined(MBEDTLS_THREADING_C)
595 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
596 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
597#endif
598
599 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000600}
601
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200602#if defined(MBEDTLS_FS_IO)
Hanno Beckera08651f2018-10-05 09:38:59 +0100603int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx,
604 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000605{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200606 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000607 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200608 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000609
610 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200611 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000612
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 Peskine82204662018-09-11 18:43:09 +0200646 n = fread( buf, 1, sizeof( buf ), f );
647 if( fread( &c, 1, 1, f ) != 0 )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100648 {
Gilles Peskine82204662018-09-11 18:43:09 +0200649 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
650 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100651 }
Gilles Peskine82204662018-09-11 18:43:09 +0200652 if( n == 0 || ferror( f ) )
653 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100654 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200655 goto exit;
656 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000657 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200658 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200659
Gilles Peskine82204662018-09-11 18:43:09 +0200660 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
661
662exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500663 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200664 if( f != NULL )
665 fclose( f );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100666 if( ret != 0 )
667 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200668 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000669}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200670#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000671
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200672#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000673
ENT\stroej170f63d02020-12-28 08:50:23 -0600674/* The CTR_DRBG NIST test vectors used here are available at
675 * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip
676 *
677 * The parameters used to derive the test data are:
678 *
679 * [AES-128 use df]
680 * [PredictionResistance = True/False]
681 * [EntropyInputLen = 128]
682 * [NonceLen = 64]
683 * [PersonalizationStringLen = 128]
684 * [AdditionalInputLen = 0]
685 * [ReturnedBitsLen = 512]
686 *
687 * [AES-256 use df]
688 * [PredictionResistance = True/False]
689 * [EntropyInputLen = 256]
690 * [NonceLen = 128]
691 * [PersonalizationStringLen = 256]
692 * [AdditionalInputLen = 0]
693 * [ReturnedBitsLen = 512]
694 *
695 */
696
Gilles Peskine02e79a42019-10-07 17:06:06 +0200697#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
ENT\stroej1df307002020-12-26 12:41:04 -0600698static const unsigned char entropy_source_pr[] =
699 { 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb,
700 0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92,
701 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8,
702 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20,
703 0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0,
704 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad,
705 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200706
ENT\stroej1df307002020-12-26 12:41:04 -0600707static const unsigned char entropy_source_nopr[] =
708 { 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45,
709 0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9,
710 0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20,
711 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f,
712 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c };
713
stroebeljcd4de1b52021-01-04 18:14:32 -0600714static const unsigned char pers_pr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600715 { 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a,
716 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad };
717
stroebeljcd4de1b52021-01-04 18:14:32 -0600718static const unsigned char pers_nopr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600719 { 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c,
720 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f };
721
722static const unsigned char result_pr[] =
723 { 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66,
724 0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff,
725 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10,
726 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30,
727 0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4,
728 0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc,
729 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06,
730 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf };
731
732static const unsigned char result_nopr[] =
733 { 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13,
734 0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0,
735 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf,
736 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2,
737 0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7,
738 0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2,
739 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02,
740 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200741#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000742
ENT\stroej1df307002020-12-26 12:41:04 -0600743static const unsigned char entropy_source_pr[] =
744 { 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49,
745 0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a,
746 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85,
747 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e,
748 0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15,
749 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45,
750 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8,
751 0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c,
752 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3,
753 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce,
754 0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e,
755 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76,
756 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77,
757 0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe };
758
759static const unsigned char entropy_source_nopr[] =
760 { 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d,
761 0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0,
762 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73,
763 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c,
764 0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2,
765 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1,
766 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a,
767 0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb,
768 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a,
769 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 };
770
stroebeljcd4de1b52021-01-04 18:14:32 -0600771static const unsigned char pers_pr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600772 { 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33,
773 0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e,
774 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0,
775 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 };
776
stroebeljcd4de1b52021-01-04 18:14:32 -0600777static const unsigned char pers_nopr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600778 { 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29,
779 0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf,
780 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb,
781 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b };
782
783static const unsigned char result_pr[] =
784 { 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85,
785 0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d,
786 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62,
787 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d,
788 0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb,
789 0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39,
790 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40,
791 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 };
792
793static const unsigned char result_nopr[] =
794 { 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad,
795 0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3,
796 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b,
797 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14,
798 0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54,
799 0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30,
800 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a,
801 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200802#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000803
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100804static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200805static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
806 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000807{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100808 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000809 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100810 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000811 return( 0 );
812}
813
Paul Bakker7dc4c442014-02-01 22:50:26 +0100814#define CHK( c ) if( (c) != 0 ) \
815 { \
816 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200817 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100818 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100819 }
820
stroebeljcd4de1b52021-01-04 18:14:32 -0600821#define SELF_TEST_OUPUT_DISCARD_LENGTH 64
822
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000823/*
824 * Checkup routine
825 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200826int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000827{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200828 mbedtls_ctr_drbg_context ctx;
stroebeljcd4de1b52021-01-04 18:14:32 -0600829 unsigned char buf[ sizeof( result_pr ) ];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000830
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200831 mbedtls_ctr_drbg_init( &ctx );
832
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000833 /*
834 * Based on a NIST CTR_DRBG test vector (PR = True)
835 */
836 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200837 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000838
839 test_offset = 0;
ENT\stroej1df307002020-12-26 12:41:04 -0600840 mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE );
stroebeljcd4de1b52021-01-04 18:14:32 -0600841 mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200842 CHK( mbedtls_ctr_drbg_seed( &ctx,
843 ctr_drbg_self_test_entropy,
844 (void *) entropy_source_pr,
stroebeljcd4de1b52021-01-04 18:14:32 -0600845 pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200846 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
stroebeljcd4de1b52021-01-04 18:14:32 -0600847 CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUPUT_DISCARD_LENGTH ) );
848 CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_pr ) ) );
849 CHK( memcmp( buf, result_pr, sizeof( result_pr ) ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000850
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100851 mbedtls_ctr_drbg_free( &ctx );
852
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000853 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200854 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000855
856 /*
857 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
858 */
859 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200860 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000861
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100862 mbedtls_ctr_drbg_init( &ctx );
863
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000864 test_offset = 0;
ENT\stroej1df307002020-12-26 12:41:04 -0600865 mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
stroebeljcd4de1b52021-01-04 18:14:32 -0600866 mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200867 CHK( mbedtls_ctr_drbg_seed( &ctx,
868 ctr_drbg_self_test_entropy,
869 (void *) entropy_source_nopr,
stroebeljcd4de1b52021-01-04 18:14:32 -0600870 pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200871 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
stroebeljcd4de1b52021-01-04 18:14:32 -0600872 CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUPUT_DISCARD_LENGTH ) );
873 CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_nopr ) ) );
874 CHK( memcmp( buf, result_nopr, sizeof( result_nopr ) ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000875
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100876 mbedtls_ctr_drbg_free( &ctx );
877
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000878 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200879 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000880
881 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200882 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000883
884 return( 0 );
885}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200886#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000887
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200888#endif /* MBEDTLS_CTR_DRBG_C */