blob: 93a7cdcd1ff2871947810804f1a8ae47e4b12407 [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
Hanno Beckera08651f2018-10-05 09:38:59 +0100610 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf,
611 MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200612 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000613
Hanno Beckera08651f2018-10-05 09:38:59 +0100614 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) !=
615 MBEDTLS_CTR_DRBG_MAX_INPUT )
616 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200617 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Hanno Beckera08651f2018-10-05 09:38:59 +0100618 }
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100619 else
Hanno Beckera08651f2018-10-05 09:38:59 +0100620 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100621 ret = 0;
Hanno Beckera08651f2018-10-05 09:38:59 +0100622 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000623
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100624exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500625 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200626
Paul Bakkerfc754a92011-12-05 13:23:51 +0000627 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200628 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000629}
630
Hanno Beckera08651f2018-10-05 09:38:59 +0100631int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx,
632 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000633{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100634 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200635 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000636 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200637 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200638 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000639
640 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200641 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000642
Gilles Peskine82204662018-09-11 18:43:09 +0200643 n = fread( buf, 1, sizeof( buf ), f );
644 if( fread( &c, 1, 1, f ) != 0 )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100645 {
Gilles Peskine82204662018-09-11 18:43:09 +0200646 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
647 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100648 }
Gilles Peskine82204662018-09-11 18:43:09 +0200649 if( n == 0 || ferror( f ) )
650 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100651 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200652 goto exit;
653 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000654 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200655 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200656
TRodziewicz26371e42021-06-08 16:45:41 +0200657 ret = mbedtls_ctr_drbg_update( ctx, buf, n );
Gilles Peskine82204662018-09-11 18:43:09 +0200658
659exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500660 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200661 if( f != NULL )
662 fclose( f );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100663 if( ret != 0 )
664 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200665 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000666}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200667#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000668
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200669#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000670
ENT\stroej170f63d02020-12-28 08:50:23 -0600671/* The CTR_DRBG NIST test vectors used here are available at
672 * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip
673 *
674 * The parameters used to derive the test data are:
675 *
676 * [AES-128 use df]
677 * [PredictionResistance = True/False]
678 * [EntropyInputLen = 128]
679 * [NonceLen = 64]
680 * [PersonalizationStringLen = 128]
681 * [AdditionalInputLen = 0]
682 * [ReturnedBitsLen = 512]
683 *
684 * [AES-256 use df]
685 * [PredictionResistance = True/False]
686 * [EntropyInputLen = 256]
687 * [NonceLen = 128]
688 * [PersonalizationStringLen = 256]
689 * [AdditionalInputLen = 0]
690 * [ReturnedBitsLen = 512]
691 *
692 */
693
Gilles Peskine02e79a42019-10-07 17:06:06 +0200694#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
ENT\stroej1df307002020-12-26 12:41:04 -0600695static const unsigned char entropy_source_pr[] =
696 { 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb,
697 0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92,
698 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8,
699 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20,
700 0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0,
701 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad,
702 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200703
ENT\stroej1df307002020-12-26 12:41:04 -0600704static const unsigned char entropy_source_nopr[] =
705 { 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45,
706 0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9,
707 0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20,
708 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f,
709 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c };
710
stroebeljcd4de1b52021-01-04 18:14:32 -0600711static const unsigned char pers_pr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600712 { 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a,
713 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad };
714
stroebeljcd4de1b52021-01-04 18:14:32 -0600715static const unsigned char pers_nopr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600716 { 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c,
717 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f };
718
719static const unsigned char result_pr[] =
720 { 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66,
721 0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff,
722 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10,
723 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30,
724 0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4,
725 0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc,
726 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06,
727 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf };
728
729static const unsigned char result_nopr[] =
730 { 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13,
731 0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0,
732 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf,
733 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2,
734 0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7,
735 0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2,
736 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02,
737 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200738#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000739
ENT\stroej1df307002020-12-26 12:41:04 -0600740static const unsigned char entropy_source_pr[] =
741 { 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49,
742 0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a,
743 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85,
744 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e,
745 0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15,
746 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45,
747 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8,
748 0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c,
749 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3,
750 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce,
751 0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e,
752 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76,
753 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77,
754 0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe };
755
756static const unsigned char entropy_source_nopr[] =
757 { 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d,
758 0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0,
759 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73,
760 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c,
761 0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2,
762 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1,
763 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a,
764 0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb,
765 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a,
766 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 };
767
stroebeljcd4de1b52021-01-04 18:14:32 -0600768static const unsigned char pers_pr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600769 { 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33,
770 0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e,
771 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0,
772 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 };
773
stroebeljcd4de1b52021-01-04 18:14:32 -0600774static const unsigned char pers_nopr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600775 { 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29,
776 0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf,
777 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb,
778 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b };
779
780static const unsigned char result_pr[] =
781 { 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85,
782 0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d,
783 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62,
784 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d,
785 0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb,
786 0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39,
787 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40,
788 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 };
789
790static const unsigned char result_nopr[] =
791 { 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad,
792 0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3,
793 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b,
794 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14,
795 0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54,
796 0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30,
797 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a,
798 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200799#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000800
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100801static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200802static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
803 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000804{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100805 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000806 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100807 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000808 return( 0 );
809}
810
Paul Bakker7dc4c442014-02-01 22:50:26 +0100811#define CHK( c ) if( (c) != 0 ) \
812 { \
813 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200814 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100815 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100816 }
817
stroebeljcd4de1b52021-01-04 18:14:32 -0600818#define SELF_TEST_OUPUT_DISCARD_LENGTH 64
819
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000820/*
821 * Checkup routine
822 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200823int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000824{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200825 mbedtls_ctr_drbg_context ctx;
stroebeljcd4de1b52021-01-04 18:14:32 -0600826 unsigned char buf[ sizeof( result_pr ) ];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000827
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200828 mbedtls_ctr_drbg_init( &ctx );
829
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000830 /*
831 * Based on a NIST CTR_DRBG test vector (PR = True)
832 */
833 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200834 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000835
836 test_offset = 0;
ENT\stroej1df307002020-12-26 12:41:04 -0600837 mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE );
stroebeljcd4de1b52021-01-04 18:14:32 -0600838 mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200839 CHK( mbedtls_ctr_drbg_seed( &ctx,
840 ctr_drbg_self_test_entropy,
841 (void *) entropy_source_pr,
stroebeljcd4de1b52021-01-04 18:14:32 -0600842 pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200843 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
stroebeljcd4de1b52021-01-04 18:14:32 -0600844 CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUPUT_DISCARD_LENGTH ) );
845 CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_pr ) ) );
846 CHK( memcmp( buf, result_pr, sizeof( result_pr ) ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000847
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100848 mbedtls_ctr_drbg_free( &ctx );
849
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000850 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200851 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000852
853 /*
854 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
855 */
856 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200857 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000858
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100859 mbedtls_ctr_drbg_init( &ctx );
860
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000861 test_offset = 0;
ENT\stroej1df307002020-12-26 12:41:04 -0600862 mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
stroebeljcd4de1b52021-01-04 18:14:32 -0600863 mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200864 CHK( mbedtls_ctr_drbg_seed( &ctx,
865 ctr_drbg_self_test_entropy,
866 (void *) entropy_source_nopr,
stroebeljcd4de1b52021-01-04 18:14:32 -0600867 pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200868 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
stroebeljcd4de1b52021-01-04 18:14:32 -0600869 CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUPUT_DISCARD_LENGTH ) );
870 CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_nopr ) ) );
871 CHK( memcmp( buf, result_nopr, sizeof( result_nopr ) ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000872
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100873 mbedtls_ctr_drbg_free( &ctx );
874
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000875 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200876 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000877
878 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200879 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000880
881 return( 0 );
882}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200883#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000884
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200885#endif /* MBEDTLS_CTR_DRBG_C */