blob: 54843a7be6b8f6c082dff77687f45c2fcd3f9ae3 [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
58#if defined(MBEDTLS_THREADING_C)
59 mbedtls_mutex_init( &ctx->mutex );
60#endif
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020061}
62
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020063void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
Paul Bakkerfff03662014-06-18 16:21:25 +020064{
65 if( ctx == NULL )
66 return;
67
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010068#if defined(MBEDTLS_THREADING_C)
69 mbedtls_mutex_free( &ctx->mutex );
70#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020071 mbedtls_aes_free( &ctx->aes_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050072 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Paul Bakkerfff03662014-06-18 16:21:25 +020073}
74
Hanno Beckera08651f2018-10-05 09:38:59 +010075void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx,
76 int resistance )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000077{
78 ctx->prediction_resistance = resistance;
79}
80
Hanno Beckera08651f2018-10-05 09:38:59 +010081void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx,
82 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000083{
84 ctx->entropy_len = len;
85}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +020086
Gilles Peskine9be50982019-10-22 18:42:27 +020087int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx,
88 size_t len )
89{
90 /* If mbedtls_ctr_drbg_seed() has already been called, it's
91 * too late. Return the error code that's closest to making sense. */
92 if( ctx->f_entropy != NULL )
93 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
94
95 if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
96 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
97#if SIZE_MAX > INT_MAX
98 /* This shouldn't be an issue because
99 * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible
100 * configuration, but make sure anyway. */
101 if( len > INT_MAX )
102 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
103#endif
104
105 /* For backward compatibility with Mbed TLS <= 2.19, store the
106 * entropy nonce length in a field that already exists, but isn't
107 * used until after the initial seeding. */
108 /* Due to the capping of len above, the value fits in an int. */
109 ctx->reseed_counter = (int) len;
110 return( 0 );
111}
112
Hanno Beckera08651f2018-10-05 09:38:59 +0100113void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx,
114 int interval )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000115{
116 ctx->reseed_interval = interval;
117}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200118
119static int block_cipher_df( unsigned char *output,
120 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000121{
Hanno Beckera08651f2018-10-05 09:38:59 +0100122 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
123 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200124 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
125 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
126 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100127 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200128 mbedtls_aes_context aes_ctx;
Dvir Markovich1b364992017-06-26 13:43:34 +0300129 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000130
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200131 int i, j;
132 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000133
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200134 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
135 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100136
Hanno Beckera08651f2018-10-05 09:38:59 +0100137 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
138 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200139 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000140
141 /*
142 * Construct IV (16 bytes) and S in buffer
143 * IV = Counter (in 32-bits) padded to 16 with zeroes
144 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
145 * data || 0x80
146 * (Total is padded to a multiple of 16-bytes with zeroes)
147 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200148 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000149 *p++ = ( data_len >> 24 ) & 0xff;
150 *p++ = ( data_len >> 16 ) & 0xff;
151 *p++ = ( data_len >> 8 ) & 0xff;
152 *p++ = ( data_len ) & 0xff;
153 p += 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200154 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000155 memcpy( p, data, data_len );
156 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000157
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200158 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000159
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200160 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000161 key[i] = i;
162
Hanno Beckera08651f2018-10-05 09:38:59 +0100163 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key,
164 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300165 {
166 goto exit;
167 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000168
169 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200170 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000171 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200172 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000173 {
174 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200175 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000176 use_len = buf_len;
177
178 while( use_len > 0 )
179 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200180 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000181 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200182 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
183 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
184 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000185
Hanno Beckera08651f2018-10-05 09:38:59 +0100186 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
187 chain, chain ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300188 {
189 goto exit;
190 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000191 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200192
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200193 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000194
195 /*
196 * Update IV
197 */
198 buf[3]++;
199 }
200
201 /*
202 * Do final encryption with reduced data
203 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100204 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp,
205 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300206 {
207 goto exit;
208 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200209 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000210 p = output;
211
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200212 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000213 {
Hanno Beckera08651f2018-10-05 09:38:59 +0100214 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
215 iv, iv ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300216 {
217 goto exit;
218 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200219 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
220 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000221 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300222exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200223 mbedtls_aes_free( &aes_ctx );
Dvir Markovich1b364992017-06-26 13:43:34 +0300224 /*
225 * tidy up the stack
226 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500227 mbedtls_platform_zeroize( buf, sizeof( buf ) );
228 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
229 mbedtls_platform_zeroize( key, sizeof( key ) );
230 mbedtls_platform_zeroize( chain, sizeof( chain ) );
Dvir Markovich1b364992017-06-26 13:43:34 +0300231 if( 0 != ret )
232 {
233 /*
234 * wipe partial seed from memory
235 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500236 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
Dvir Markovich1b364992017-06-26 13:43:34 +0300237 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200238
Dvir Markovich1b364992017-06-26 13:43:34 +0300239 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000240}
241
Gilles Peskineed7da592018-08-03 20:16:52 +0200242/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
243 * ctr_drbg_update_internal(ctx, provided_data)
244 * implements
245 * CTR_DRBG_Update(provided_data, Key, V)
246 * with inputs and outputs
247 * ctx->aes_ctx = Key
248 * ctx->counter = V
249 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200250static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
Hanno Beckera08651f2018-10-05 09:38:59 +0100251 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000252{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200253 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000254 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000255 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300256 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000257
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200258 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000259
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200260 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000261 {
262 /*
263 * Increase counter
264 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200265 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000266 if( ++ctx->counter[i - 1] != 0 )
267 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000268
269 /*
270 * Crypt counter block
271 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100272 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
273 ctx->counter, p ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300274 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200275 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300276 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000277
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200278 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000279 }
280
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200281 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000282 tmp[i] ^= data[i];
283
284 /*
285 * Update key and counter
286 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100287 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp,
288 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300289 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200290 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300291 }
Hanno Beckera08651f2018-10-05 09:38:59 +0100292 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
293 MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000294
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200295exit:
296 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
297 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000298}
299
Gilles Peskineed7da592018-08-03 20:16:52 +0200300/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
301 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
302 * implements
303 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
304 * security_strength) -> initial_working_state
305 * with inputs
306 * ctx->counter = all-bits-0
307 * ctx->aes_ctx = context from all-bits-0 key
308 * additional[:add_len] = entropy_input || nonce || personalization_string
309 * and with outputs
310 * ctx = initial_working_state
311 */
Gilles Peskined9199932018-09-11 16:41:54 +0200312int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
313 const unsigned char *additional,
314 size_t add_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000315{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200316 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Janos Follath24eed8d2019-11-22 13:21:35 +0000317 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000318
Gilles Peskined9199932018-09-11 16:41:54 +0200319 if( add_len == 0 )
320 return( 0 );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100321
Gilles Peskined9199932018-09-11 16:41:54 +0200322 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
323 goto exit;
324 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
325 goto exit;
326
327exit:
328 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
329 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000330}
331
Gilles Peskined9199932018-09-11 16:41:54 +0200332#if !defined(MBEDTLS_DEPRECATED_REMOVED)
333void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
334 const unsigned char *additional,
335 size_t add_len )
336{
337 /* MAX_INPUT would be more logical here, but we have to match
338 * block_cipher_df()'s limits since we can't propagate errors */
339 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
340 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
341 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
342}
343#endif /* MBEDTLS_DEPRECATED_REMOVED */
344
Gilles Peskineed7da592018-08-03 20:16:52 +0200345/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
Gilles Peskine9be50982019-10-22 18:42:27 +0200346 * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
Gilles Peskineed7da592018-08-03 20:16:52 +0200347 * implements
348 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
349 * -> new_working_state
350 * with inputs
351 * ctx contains working_state
352 * additional[:len] = additional_input
353 * and entropy_input comes from calling ctx->f_entropy
Gilles Peskine9be50982019-10-22 18:42:27 +0200354 * for (ctx->entropy_len + nonce_len) bytes
Gilles Peskineed7da592018-08-03 20:16:52 +0200355 * and with output
356 * ctx contains new_working_state
357 */
Gilles Peskine97f59ab2019-10-22 18:42:27 +0200358static int mbedtls_ctr_drbg_reseed_internal( mbedtls_ctr_drbg_context *ctx,
359 const unsigned char *additional,
360 size_t len,
361 size_t nonce_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000362{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200363 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000364 size_t seedlen = 0;
Janos Follath24eed8d2019-11-22 13:21:35 +0000365 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000366
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200367 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
368 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Gilles Peskine9be50982019-10-22 18:42:27 +0200369 if( nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
370 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
371 if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200372 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000373
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200374 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000375
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200376 /* Gather entropy_len bytes of entropy to seed state. */
377 if( 0 != ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000378 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200379 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000380 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000381 seedlen += ctx->entropy_len;
382
Gilles Peskine9be50982019-10-22 18:42:27 +0200383 /* Gather entropy for a nonce if requested. */
384 if( nonce_len != 0 )
385 {
386 if( 0 != ctx->f_entropy( ctx->p_entropy, seed, nonce_len ) )
387 {
388 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
389 }
390 seedlen += nonce_len;
391 }
392
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200393 /* Add additional data if provided. */
394 if( additional != NULL && len != 0 )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000395 {
396 memcpy( seed + seedlen, additional, len );
397 seedlen += len;
398 }
399
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200400 /* Reduce to 384 bits. */
Dvir Markovich1b364992017-06-26 13:43:34 +0300401 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200402 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000403
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200404 /* Update state. */
Dvir Markovich1b364992017-06-26 13:43:34 +0300405 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200406 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000407 ctx->reseed_counter = 1;
408
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200409exit:
410 mbedtls_platform_zeroize( seed, sizeof( seed ) );
411 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000412}
Paul Bakker9af723c2014-05-01 13:03:14 +0200413
Gilles Peskine9be50982019-10-22 18:42:27 +0200414int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
415 const unsigned char *additional, size_t len )
416{
417 return( mbedtls_ctr_drbg_reseed_internal( ctx, additional, len, 0 ) );
418}
419
Gilles Peskinee9a34542019-10-22 20:43:24 +0200420/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
421 * is sufficient to achieve the maximum security strength given the key
422 * size and entropy length. If there is enough entropy in the initial
423 * call to the entropy function to serve as both the entropy input and
424 * the nonce, don't make a second call to get a nonce. */
425static size_t good_nonce_len( size_t entropy_len )
426{
427 if( entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 )
428 return( 0 );
429 else
430 return( ( entropy_len + 1 ) / 2 );
431}
432
Gilles Peskine8bf56132019-10-02 20:31:54 +0200433/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
Gilles Peskine379561f2019-10-18 16:57:48 +0200434 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
Gilles Peskine8bf56132019-10-02 20:31:54 +0200435 * implements
436 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
437 * security_strength) -> initial_working_state
438 * with inputs
439 * custom[:len] = nonce || personalization_string
Gilles Peskine379561f2019-10-18 16:57:48 +0200440 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
Gilles Peskine8bf56132019-10-02 20:31:54 +0200441 * and with outputs
442 * ctx = initial_working_state
443 */
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200444int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
445 int (*f_entropy)(void *, unsigned char *, size_t),
446 void *p_entropy,
447 const unsigned char *custom,
448 size_t len )
Gilles Peskine8bf56132019-10-02 20:31:54 +0200449{
Janos Follath24eed8d2019-11-22 13:21:35 +0000450 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200451 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Gilles Peskinee9a34542019-10-22 20:43:24 +0200452 size_t nonce_len;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200453
454 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
455
456 mbedtls_aes_init( &ctx->aes_ctx );
457
458 ctx->f_entropy = f_entropy;
459 ctx->p_entropy = p_entropy;
460
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200461 if( ctx->entropy_len == 0 )
462 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskinee9a34542019-10-22 20:43:24 +0200463 /* ctx->reseed_counter contains the desired amount of entropy to
464 * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
465 * If it's -1, indicating that the entropy nonce length was not set
466 * explicitly, use a sufficiently large nonce for security. */
467 nonce_len = ( ctx->reseed_counter >= 0 ?
468 (size_t) ctx->reseed_counter :
469 good_nonce_len( ctx->entropy_len ) );
470
Gilles Peskine8bf56132019-10-02 20:31:54 +0200471 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
472
Gilles Peskine9be50982019-10-22 18:42:27 +0200473 /* Initialize with an empty key. */
Gilles Peskine8bf56132019-10-02 20:31:54 +0200474 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
475 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
476 {
477 return( ret );
478 }
479
Gilles Peskinee9a34542019-10-22 20:43:24 +0200480 /* Do the initial seeding. */
Gilles Peskine9be50982019-10-22 18:42:27 +0200481 if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len,
Gilles Peskinee9a34542019-10-22 20:43:24 +0200482 nonce_len ) ) != 0 )
Gilles Peskine8bf56132019-10-02 20:31:54 +0200483 {
484 return( ret );
485 }
486 return( 0 );
487}
488
Gilles Peskineed7da592018-08-03 20:16:52 +0200489/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
490 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
491 * implements
492 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
493 * -> working_state_after_reseed
494 * if required, then
495 * CTR_DRBG_Generate(working_state_after_reseed,
496 * requested_number_of_bits, additional_input)
497 * -> status, returned_bits, new_working_state
498 * with inputs
499 * ctx contains working_state
500 * requested_number_of_bits = 8 * output_len
501 * additional[:add_len] = additional_input
502 * and entropy_input comes from calling ctx->f_entropy
503 * and with outputs
504 * status = SUCCESS (this function does the reseed internally)
505 * returned_bits = output[:output_len]
506 * ctx contains new_working_state
507 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200508int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000509 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000510 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000511{
512 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200513 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
514 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000515 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200516 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000517 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000518 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000519
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200520 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
521 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000522
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200523 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
524 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000525
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200526 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000527
528 if( ctx->reseed_counter > ctx->reseed_interval ||
529 ctx->prediction_resistance )
530 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200531 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300532 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000533 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300534 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000535 add_len = 0;
536 }
537
538 if( add_len > 0 )
539 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300540 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200541 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300542 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200543 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000544 }
545
546 while( output_len > 0 )
547 {
548 /*
549 * Increase counter
550 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200551 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000552 if( ++ctx->counter[i - 1] != 0 )
553 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000554
555 /*
556 * Crypt counter block
557 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100558 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
559 ctx->counter, tmp ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300560 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200561 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300562 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000563
Hanno Beckera08651f2018-10-05 09:38:59 +0100564 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE )
565 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000566 /*
567 * Copy random block to destination
568 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000569 memcpy( p, tmp, use_len );
570 p += use_len;
571 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000572 }
573
Dvir Markovich1b364992017-06-26 13:43:34 +0300574 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200575 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000576
577 ctx->reseed_counter++;
578
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200579exit:
580 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
581 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
Gilles Peskineafaee1c2019-11-28 09:45:32 +0100582 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000583}
584
Hanno Beckera08651f2018-10-05 09:38:59 +0100585int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output,
586 size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000587{
Janos Follath24eed8d2019-11-22 13:21:35 +0000588 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100589 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
590
591#if defined(MBEDTLS_THREADING_C)
592 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
593 return( ret );
594#endif
595
596 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
597
598#if defined(MBEDTLS_THREADING_C)
599 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
600 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
601#endif
602
603 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000604}
605
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200606#if defined(MBEDTLS_FS_IO)
Hanno Beckera08651f2018-10-05 09:38:59 +0100607int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx,
608 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000609{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200610 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000611 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200612 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000613
614 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200615 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000616
Hanno Beckera08651f2018-10-05 09:38:59 +0100617 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf,
618 MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200619 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000620
Hanno Beckera08651f2018-10-05 09:38:59 +0100621 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) !=
622 MBEDTLS_CTR_DRBG_MAX_INPUT )
623 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200624 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Hanno Beckera08651f2018-10-05 09:38:59 +0100625 }
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100626 else
Hanno Beckera08651f2018-10-05 09:38:59 +0100627 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100628 ret = 0;
Hanno Beckera08651f2018-10-05 09:38:59 +0100629 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000630
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100631exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500632 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200633
Paul Bakkerfc754a92011-12-05 13:23:51 +0000634 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200635 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000636}
637
Hanno Beckera08651f2018-10-05 09:38:59 +0100638int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx,
639 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000640{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100641 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200642 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000643 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200644 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200645 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000646
647 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200648 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000649
Gilles Peskine82204662018-09-11 18:43:09 +0200650 n = fread( buf, 1, sizeof( buf ), f );
651 if( fread( &c, 1, 1, f ) != 0 )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100652 {
Gilles Peskine82204662018-09-11 18:43:09 +0200653 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
654 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100655 }
Gilles Peskine82204662018-09-11 18:43:09 +0200656 if( n == 0 || ferror( f ) )
657 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100658 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200659 goto exit;
660 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000661 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200662 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200663
Gilles Peskine82204662018-09-11 18:43:09 +0200664 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
665
666exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500667 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200668 if( f != NULL )
669 fclose( f );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100670 if( ret != 0 )
671 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200672 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000673}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200674#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000675
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200676#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000677
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000678static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000679 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
680 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
681 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
682 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
683 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
684 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
685 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
686 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
687 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
688 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
689 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
690 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
691
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000692static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000693 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
694 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
695 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
696 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
697 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
698 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
699 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
700 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
701
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100702static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000703 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
704 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
705
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100706static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000707 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
708 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
709
Gilles Peskine02e79a42019-10-07 17:06:06 +0200710#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
711static const unsigned char result_pr[16] =
712 { 0x95, 0x3c, 0xa5, 0xbd, 0x44, 0x1, 0x34, 0xb7,
713 0x13, 0x58, 0x3e, 0x6a, 0x6c, 0x7e, 0x88, 0x8a };
714
715static const unsigned char result_nopr[16] =
716 { 0x6c, 0x25, 0x27, 0x95, 0xa3, 0x62, 0xd6, 0xdb,
717 0x90, 0xfd, 0x69, 0xb5, 0x42, 0x9, 0x4b, 0x84 };
718#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100719static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000720 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
721 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
722
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100723static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000724 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
725 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200726#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000727
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100728static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200729static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
730 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000731{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100732 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000733 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100734 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000735 return( 0 );
736}
737
Paul Bakker7dc4c442014-02-01 22:50:26 +0100738#define CHK( c ) if( (c) != 0 ) \
739 { \
740 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200741 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100742 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100743 }
744
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000745/*
746 * Checkup routine
747 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200748int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000749{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200750 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000751 unsigned char buf[16];
752
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200753 mbedtls_ctr_drbg_init( &ctx );
754
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000755 /*
756 * Based on a NIST CTR_DRBG test vector (PR = True)
757 */
758 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200759 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000760
761 test_offset = 0;
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200762 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
Gilles Peskine0ed378a2019-10-22 20:33:56 +0200763 mbedtls_ctr_drbg_set_nonce_len( &ctx, 0 );
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200764 CHK( mbedtls_ctr_drbg_seed( &ctx,
765 ctr_drbg_self_test_entropy,
766 (void *) entropy_source_pr,
767 nonce_pers_pr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200768 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
769 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
770 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
771 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000772
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100773 mbedtls_ctr_drbg_free( &ctx );
774
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000775 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200776 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000777
778 /*
779 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
780 */
781 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200782 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000783
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100784 mbedtls_ctr_drbg_init( &ctx );
785
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000786 test_offset = 0;
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200787 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
Gilles Peskine0ed378a2019-10-22 20:33:56 +0200788 mbedtls_ctr_drbg_set_nonce_len( &ctx, 0 );
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200789 CHK( mbedtls_ctr_drbg_seed( &ctx,
790 ctr_drbg_self_test_entropy,
791 (void *) entropy_source_nopr,
792 nonce_pers_nopr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200793 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
794 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
795 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100796 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000797
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100798 mbedtls_ctr_drbg_free( &ctx );
799
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000800 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200801 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000802
803 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200804 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000805
806 return( 0 );
807}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200808#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000809
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200810#endif /* MBEDTLS_CTR_DRBG_C */