blob: 51a4129eb1da6a6d95c6b8994a02cdad42f8a175 [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;
59
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010060#if defined(MBEDTLS_THREADING_C)
61 mbedtls_mutex_init( &ctx->mutex );
62#endif
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020063}
64
Gavin Acquroff6aceb512020-03-01 17:06:11 -080065/*
66 * This function resets CTR_DRBG context to the state immediately
67 * after initial call of mbedtls_ctr_drbg_init().
68 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020069void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
Paul Bakkerfff03662014-06-18 16:21:25 +020070{
71 if( ctx == NULL )
72 return;
73
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010074#if defined(MBEDTLS_THREADING_C)
75 mbedtls_mutex_free( &ctx->mutex );
76#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020077 mbedtls_aes_free( &ctx->aes_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050078 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Gavin Acquroff6aceb512020-03-01 17:06:11 -080079 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
80 ctx->reseed_counter = -1;
81#if defined(MBEDTLS_THREADING_C)
82 mbedtls_mutex_init( &ctx->mutex );
83#endif
Paul Bakkerfff03662014-06-18 16:21:25 +020084}
85
Hanno Beckera08651f2018-10-05 09:38:59 +010086void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx,
87 int resistance )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000088{
89 ctx->prediction_resistance = resistance;
90}
91
Hanno Beckera08651f2018-10-05 09:38:59 +010092void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx,
93 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000094{
95 ctx->entropy_len = len;
96}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +020097
Gilles Peskine9be50982019-10-22 18:42:27 +020098int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx,
99 size_t len )
100{
101 /* If mbedtls_ctr_drbg_seed() has already been called, it's
102 * too late. Return the error code that's closest to making sense. */
103 if( ctx->f_entropy != NULL )
104 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
105
106 if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
107 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
108#if SIZE_MAX > INT_MAX
109 /* This shouldn't be an issue because
110 * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible
111 * configuration, but make sure anyway. */
112 if( len > INT_MAX )
113 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
114#endif
115
116 /* For backward compatibility with Mbed TLS <= 2.19, store the
117 * entropy nonce length in a field that already exists, but isn't
118 * used until after the initial seeding. */
119 /* Due to the capping of len above, the value fits in an int. */
120 ctx->reseed_counter = (int) len;
121 return( 0 );
122}
123
Hanno Beckera08651f2018-10-05 09:38:59 +0100124void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx,
125 int interval )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000126{
127 ctx->reseed_interval = interval;
128}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200129
130static int block_cipher_df( unsigned char *output,
131 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000132{
Hanno Beckera08651f2018-10-05 09:38:59 +0100133 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
134 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200135 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
136 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
137 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100138 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200139 mbedtls_aes_context aes_ctx;
Dvir Markovich1b364992017-06-26 13:43:34 +0300140 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000141
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200142 int i, j;
143 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000144
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200145 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
146 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100147
Hanno Beckera08651f2018-10-05 09:38:59 +0100148 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
149 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200150 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000151
152 /*
153 * Construct IV (16 bytes) and S in buffer
154 * IV = Counter (in 32-bits) padded to 16 with zeroes
155 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
156 * data || 0x80
157 * (Total is padded to a multiple of 16-bytes with zeroes)
158 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200159 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000160 *p++ = ( data_len >> 24 ) & 0xff;
161 *p++ = ( data_len >> 16 ) & 0xff;
162 *p++ = ( data_len >> 8 ) & 0xff;
163 *p++ = ( data_len ) & 0xff;
164 p += 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200165 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000166 memcpy( p, data, data_len );
167 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000168
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200169 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000170
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200171 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000172 key[i] = i;
173
Hanno Beckera08651f2018-10-05 09:38:59 +0100174 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key,
175 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300176 {
177 goto exit;
178 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000179
180 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200181 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000182 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200183 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000184 {
185 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200186 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000187 use_len = buf_len;
188
189 while( use_len > 0 )
190 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200191 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000192 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200193 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
194 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
195 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000196
Hanno Beckera08651f2018-10-05 09:38:59 +0100197 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
198 chain, chain ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300199 {
200 goto exit;
201 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000202 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200203
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200204 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000205
206 /*
207 * Update IV
208 */
209 buf[3]++;
210 }
211
212 /*
213 * Do final encryption with reduced data
214 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100215 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp,
216 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300217 {
218 goto exit;
219 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200220 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000221 p = output;
222
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200223 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000224 {
Hanno Beckera08651f2018-10-05 09:38:59 +0100225 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
226 iv, iv ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300227 {
228 goto exit;
229 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200230 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
231 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000232 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300233exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200234 mbedtls_aes_free( &aes_ctx );
Dvir Markovich1b364992017-06-26 13:43:34 +0300235 /*
236 * tidy up the stack
237 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500238 mbedtls_platform_zeroize( buf, sizeof( buf ) );
239 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
240 mbedtls_platform_zeroize( key, sizeof( key ) );
241 mbedtls_platform_zeroize( chain, sizeof( chain ) );
Dvir Markovich1b364992017-06-26 13:43:34 +0300242 if( 0 != ret )
243 {
244 /*
245 * wipe partial seed from memory
246 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500247 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
Dvir Markovich1b364992017-06-26 13:43:34 +0300248 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200249
Dvir Markovich1b364992017-06-26 13:43:34 +0300250 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000251}
252
Gilles Peskineed7da592018-08-03 20:16:52 +0200253/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
254 * ctr_drbg_update_internal(ctx, provided_data)
255 * implements
256 * CTR_DRBG_Update(provided_data, Key, V)
257 * with inputs and outputs
258 * ctx->aes_ctx = Key
259 * ctx->counter = V
260 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200261static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
Hanno Beckera08651f2018-10-05 09:38:59 +0100262 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000263{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200264 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000265 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000266 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300267 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000268
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200269 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000270
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200271 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000272 {
273 /*
274 * Increase counter
275 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200276 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000277 if( ++ctx->counter[i - 1] != 0 )
278 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000279
280 /*
281 * Crypt counter block
282 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100283 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
284 ctx->counter, p ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300285 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200286 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300287 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000288
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200289 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000290 }
291
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200292 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000293 tmp[i] ^= data[i];
294
295 /*
296 * Update key and counter
297 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100298 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp,
299 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300300 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200301 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300302 }
Hanno Beckera08651f2018-10-05 09:38:59 +0100303 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
304 MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000305
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200306exit:
307 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
308 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000309}
310
Gilles Peskineed7da592018-08-03 20:16:52 +0200311/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
312 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
313 * implements
314 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
315 * security_strength) -> initial_working_state
316 * with inputs
317 * ctx->counter = all-bits-0
318 * ctx->aes_ctx = context from all-bits-0 key
319 * additional[:add_len] = entropy_input || nonce || personalization_string
320 * and with outputs
321 * ctx = initial_working_state
322 */
Gilles Peskined9199932018-09-11 16:41:54 +0200323int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
324 const unsigned char *additional,
325 size_t add_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000326{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200327 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Janos Follath24eed8d2019-11-22 13:21:35 +0000328 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000329
Gilles Peskined9199932018-09-11 16:41:54 +0200330 if( add_len == 0 )
331 return( 0 );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100332
Gilles Peskined9199932018-09-11 16:41:54 +0200333 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
334 goto exit;
335 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
336 goto exit;
337
338exit:
339 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
340 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000341}
342
Gilles Peskined9199932018-09-11 16:41:54 +0200343#if !defined(MBEDTLS_DEPRECATED_REMOVED)
344void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
345 const unsigned char *additional,
346 size_t add_len )
347{
348 /* MAX_INPUT would be more logical here, but we have to match
349 * block_cipher_df()'s limits since we can't propagate errors */
350 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
351 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
352 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
353}
354#endif /* MBEDTLS_DEPRECATED_REMOVED */
355
Gilles Peskineed7da592018-08-03 20:16:52 +0200356/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
Gilles Peskine9be50982019-10-22 18:42:27 +0200357 * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
Gilles Peskineed7da592018-08-03 20:16:52 +0200358 * implements
359 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
360 * -> new_working_state
361 * with inputs
362 * ctx contains working_state
363 * additional[:len] = additional_input
364 * and entropy_input comes from calling ctx->f_entropy
Gilles Peskine9be50982019-10-22 18:42:27 +0200365 * for (ctx->entropy_len + nonce_len) bytes
Gilles Peskineed7da592018-08-03 20:16:52 +0200366 * and with output
367 * ctx contains new_working_state
368 */
Gilles Peskine97f59ab2019-10-22 18:42:27 +0200369static int mbedtls_ctr_drbg_reseed_internal( mbedtls_ctr_drbg_context *ctx,
370 const unsigned char *additional,
371 size_t len,
372 size_t nonce_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000373{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200374 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000375 size_t seedlen = 0;
Janos Follath24eed8d2019-11-22 13:21:35 +0000376 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000377
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200378 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
379 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Gilles Peskine9be50982019-10-22 18:42:27 +0200380 if( nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
381 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
382 if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200383 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000384
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200385 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000386
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200387 /* Gather entropy_len bytes of entropy to seed state. */
388 if( 0 != ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000389 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200390 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000391 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000392 seedlen += ctx->entropy_len;
393
Gilles Peskine9be50982019-10-22 18:42:27 +0200394 /* Gather entropy for a nonce if requested. */
395 if( nonce_len != 0 )
396 {
ENT\stroej14b919862020-12-23 17:28:33 -0600397 if( 0 != ctx->f_entropy( ctx->p_entropy, seed + seedlen, nonce_len ) )
Gilles Peskine9be50982019-10-22 18:42:27 +0200398 {
399 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
400 }
401 seedlen += nonce_len;
402 }
403
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200404 /* Add additional data if provided. */
405 if( additional != NULL && len != 0 )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000406 {
407 memcpy( seed + seedlen, additional, len );
408 seedlen += len;
409 }
410
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200411 /* Reduce to 384 bits. */
Dvir Markovich1b364992017-06-26 13:43:34 +0300412 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200413 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000414
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200415 /* Update state. */
Dvir Markovich1b364992017-06-26 13:43:34 +0300416 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200417 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000418 ctx->reseed_counter = 1;
419
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200420exit:
421 mbedtls_platform_zeroize( seed, sizeof( seed ) );
422 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000423}
Paul Bakker9af723c2014-05-01 13:03:14 +0200424
Gilles Peskine9be50982019-10-22 18:42:27 +0200425int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
426 const unsigned char *additional, size_t len )
427{
428 return( mbedtls_ctr_drbg_reseed_internal( ctx, additional, len, 0 ) );
429}
430
Gilles Peskinee9a34542019-10-22 20:43:24 +0200431/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
432 * is sufficient to achieve the maximum security strength given the key
433 * size and entropy length. If there is enough entropy in the initial
434 * call to the entropy function to serve as both the entropy input and
435 * the nonce, don't make a second call to get a nonce. */
436static size_t good_nonce_len( size_t entropy_len )
437{
438 if( entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 )
439 return( 0 );
440 else
441 return( ( entropy_len + 1 ) / 2 );
442}
443
Gilles Peskine8bf56132019-10-02 20:31:54 +0200444/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
Gilles Peskine379561f2019-10-18 16:57:48 +0200445 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
Gilles Peskine8bf56132019-10-02 20:31:54 +0200446 * implements
447 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
448 * security_strength) -> initial_working_state
449 * with inputs
450 * custom[:len] = nonce || personalization_string
Gilles Peskine379561f2019-10-18 16:57:48 +0200451 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
Gilles Peskine8bf56132019-10-02 20:31:54 +0200452 * and with outputs
453 * ctx = initial_working_state
454 */
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200455int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
456 int (*f_entropy)(void *, unsigned char *, size_t),
457 void *p_entropy,
458 const unsigned char *custom,
459 size_t len )
Gilles Peskine8bf56132019-10-02 20:31:54 +0200460{
Janos Follath24eed8d2019-11-22 13:21:35 +0000461 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200462 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Gilles Peskinee9a34542019-10-22 20:43:24 +0200463 size_t nonce_len;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200464
465 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
466
467 mbedtls_aes_init( &ctx->aes_ctx );
468
469 ctx->f_entropy = f_entropy;
470 ctx->p_entropy = p_entropy;
471
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200472 if( ctx->entropy_len == 0 )
473 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskinee9a34542019-10-22 20:43:24 +0200474 /* ctx->reseed_counter contains the desired amount of entropy to
475 * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
476 * If it's -1, indicating that the entropy nonce length was not set
477 * explicitly, use a sufficiently large nonce for security. */
478 nonce_len = ( ctx->reseed_counter >= 0 ?
479 (size_t) ctx->reseed_counter :
480 good_nonce_len( ctx->entropy_len ) );
481
Gilles Peskine9be50982019-10-22 18:42:27 +0200482 /* Initialize with an empty key. */
Gilles Peskine8bf56132019-10-02 20:31:54 +0200483 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
484 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
485 {
486 return( ret );
487 }
488
Gilles Peskinee9a34542019-10-22 20:43:24 +0200489 /* Do the initial seeding. */
Gilles Peskine9be50982019-10-22 18:42:27 +0200490 if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len,
Gilles Peskinee9a34542019-10-22 20:43:24 +0200491 nonce_len ) ) != 0 )
Gilles Peskine8bf56132019-10-02 20:31:54 +0200492 {
493 return( ret );
494 }
495 return( 0 );
496}
497
Gilles Peskineed7da592018-08-03 20:16:52 +0200498/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
499 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
500 * implements
501 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
502 * -> working_state_after_reseed
503 * if required, then
504 * CTR_DRBG_Generate(working_state_after_reseed,
505 * requested_number_of_bits, additional_input)
506 * -> status, returned_bits, new_working_state
507 * with inputs
508 * ctx contains working_state
509 * requested_number_of_bits = 8 * output_len
510 * additional[:add_len] = additional_input
511 * and entropy_input comes from calling ctx->f_entropy
512 * and with outputs
513 * status = SUCCESS (this function does the reseed internally)
514 * returned_bits = output[:output_len]
515 * ctx contains new_working_state
516 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200517int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000518 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000519 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000520{
521 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200522 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
523 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000524 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200525 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000526 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000527 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000528
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200529 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
530 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000531
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200532 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
533 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000534
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200535 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000536
537 if( ctx->reseed_counter > ctx->reseed_interval ||
538 ctx->prediction_resistance )
539 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200540 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300541 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000542 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300543 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000544 add_len = 0;
545 }
546
547 if( add_len > 0 )
548 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300549 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200550 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300551 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200552 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000553 }
554
555 while( output_len > 0 )
556 {
557 /*
558 * Increase counter
559 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200560 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000561 if( ++ctx->counter[i - 1] != 0 )
562 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000563
564 /*
565 * Crypt counter block
566 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100567 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
568 ctx->counter, tmp ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300569 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200570 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300571 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000572
Hanno Beckera08651f2018-10-05 09:38:59 +0100573 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE )
574 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000575 /*
576 * Copy random block to destination
577 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000578 memcpy( p, tmp, use_len );
579 p += use_len;
580 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000581 }
582
Dvir Markovich1b364992017-06-26 13:43:34 +0300583 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200584 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000585
586 ctx->reseed_counter++;
587
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200588exit:
589 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
590 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
Gilles Peskineafaee1c2019-11-28 09:45:32 +0100591 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000592}
593
Hanno Beckera08651f2018-10-05 09:38:59 +0100594int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output,
595 size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000596{
Janos Follath24eed8d2019-11-22 13:21:35 +0000597 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100598 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
599
600#if defined(MBEDTLS_THREADING_C)
601 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
602 return( ret );
603#endif
604
605 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
606
607#if defined(MBEDTLS_THREADING_C)
608 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
609 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
610#endif
611
612 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000613}
614
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200615#if defined(MBEDTLS_FS_IO)
Hanno Beckera08651f2018-10-05 09:38:59 +0100616int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx,
617 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000618{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200619 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000620 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200621 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000622
623 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200624 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000625
Hanno Beckera08651f2018-10-05 09:38:59 +0100626 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf,
627 MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200628 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000629
Hanno Beckera08651f2018-10-05 09:38:59 +0100630 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) !=
631 MBEDTLS_CTR_DRBG_MAX_INPUT )
632 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200633 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Hanno Beckera08651f2018-10-05 09:38:59 +0100634 }
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100635 else
Hanno Beckera08651f2018-10-05 09:38:59 +0100636 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100637 ret = 0;
Hanno Beckera08651f2018-10-05 09:38:59 +0100638 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000639
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100640exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500641 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200642
Paul Bakkerfc754a92011-12-05 13:23:51 +0000643 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200644 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000645}
646
Hanno Beckera08651f2018-10-05 09:38:59 +0100647int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx,
648 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000649{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100650 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200651 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000652 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200653 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200654 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000655
656 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200657 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000658
Gilles Peskine82204662018-09-11 18:43:09 +0200659 n = fread( buf, 1, sizeof( buf ), f );
660 if( fread( &c, 1, 1, f ) != 0 )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100661 {
Gilles Peskine82204662018-09-11 18:43:09 +0200662 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
663 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100664 }
Gilles Peskine82204662018-09-11 18:43:09 +0200665 if( n == 0 || ferror( f ) )
666 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100667 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200668 goto exit;
669 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000670 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200671 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200672
Gilles Peskine82204662018-09-11 18:43:09 +0200673 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
674
675exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500676 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200677 if( f != NULL )
678 fclose( f );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100679 if( ret != 0 )
680 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200681 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000682}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200683#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000684
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200685#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000686
Gilles Peskine02e79a42019-10-07 17:06:06 +0200687#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
ENT\stroej1df307002020-12-26 12:41:04 -0600688static const unsigned char entropy_source_pr[] =
689 { 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb,
690 0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92,
691 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8,
692 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20,
693 0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0,
694 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad,
695 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200696
ENT\stroej1df307002020-12-26 12:41:04 -0600697static const unsigned char entropy_source_nopr[] =
698 { 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45,
699 0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9,
700 0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20,
701 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f,
702 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c };
703
704static const unsigned char nonce_pers_pr[] =
705 { 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a,
706 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad };
707
708static const unsigned char nonce_pers_nopr[] =
709 { 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c,
710 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f };
711
712static const unsigned char result_pr[] =
713 { 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66,
714 0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff,
715 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10,
716 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30,
717 0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4,
718 0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc,
719 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06,
720 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf };
721
722static const unsigned char result_nopr[] =
723 { 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13,
724 0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0,
725 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf,
726 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2,
727 0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7,
728 0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2,
729 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02,
730 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200731#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000732
ENT\stroej1df307002020-12-26 12:41:04 -0600733static const unsigned char entropy_source_pr[] =
734 { 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49,
735 0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a,
736 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85,
737 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e,
738 0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15,
739 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45,
740 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8,
741 0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c,
742 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3,
743 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce,
744 0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e,
745 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76,
746 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77,
747 0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe };
748
749static const unsigned char entropy_source_nopr[] =
750 { 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d,
751 0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0,
752 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73,
753 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c,
754 0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2,
755 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1,
756 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a,
757 0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb,
758 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a,
759 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 };
760
761static const unsigned char nonce_pers_pr[] =
762 { 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33,
763 0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e,
764 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0,
765 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 };
766
767static const unsigned char nonce_pers_nopr[] =
768 { 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29,
769 0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf,
770 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb,
771 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b };
772
773static const unsigned char result_pr[] =
774 { 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85,
775 0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d,
776 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62,
777 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d,
778 0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb,
779 0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39,
780 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40,
781 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 };
782
783static const unsigned char result_nopr[] =
784 { 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad,
785 0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3,
786 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b,
787 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14,
788 0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54,
789 0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30,
790 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a,
791 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200792#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000793
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100794static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200795static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
796 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000797{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100798 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000799 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100800 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000801 return( 0 );
802}
803
Paul Bakker7dc4c442014-02-01 22:50:26 +0100804#define CHK( c ) if( (c) != 0 ) \
805 { \
806 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200807 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100808 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100809 }
810
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000811/*
812 * Checkup routine
813 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200814int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000815{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200816 mbedtls_ctr_drbg_context ctx;
ENT\stroej1df307002020-12-26 12:41:04 -0600817 unsigned char buf[64];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000818
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200819 mbedtls_ctr_drbg_init( &ctx );
820
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000821 /*
822 * Based on a NIST CTR_DRBG test vector (PR = True)
823 */
824 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200825 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000826
827 test_offset = 0;
ENT\stroej1df307002020-12-26 12:41:04 -0600828 mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE );
829 mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE >> 1 );
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200830 CHK( mbedtls_ctr_drbg_seed( &ctx,
831 ctr_drbg_self_test_entropy,
832 (void *) entropy_source_pr,
ENT\stroej1df307002020-12-26 12:41:04 -0600833 nonce_pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200834 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
ENT\stroej1df307002020-12-26 12:41:04 -0600835 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 64 ) );
836 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 64 ) );
837 CHK( memcmp( buf, result_pr, 64 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000838
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100839 mbedtls_ctr_drbg_free( &ctx );
840
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000841 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200842 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000843
844 /*
845 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
846 */
847 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200848 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000849
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100850 mbedtls_ctr_drbg_init( &ctx );
851
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000852 test_offset = 0;
ENT\stroej1df307002020-12-26 12:41:04 -0600853 mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
854 mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE >> 1 );
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200855 CHK( mbedtls_ctr_drbg_seed( &ctx,
856 ctr_drbg_self_test_entropy,
857 (void *) entropy_source_nopr,
ENT\stroej1df307002020-12-26 12:41:04 -0600858 nonce_pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200859 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
ENT\stroej1df307002020-12-26 12:41:04 -0600860 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 64 ) );
861 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 64 ) );
862 CHK( memcmp( buf, result_nopr, 64 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000863
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100864 mbedtls_ctr_drbg_free( &ctx );
865
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000866 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200867 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000868
869 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200870 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000871
872 return( 0 );
873}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200874#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000875
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200876#endif /* MBEDTLS_CTR_DRBG_C */