blob: f5c5e7b612b92efacad71eb1a24b398af13c6c1d [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é-Gonnard7f809972015-03-09 17:05:11 +000039#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010040
Paul Bakker18d32912011-12-10 21:42:49 +000041/*
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020042 * CTR_DRBG context initialization
43 */
44void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
45{
46 memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
kXuan11e93102022-08-10 16:32:06 +080047 mbedtls_aes_init( &ctx->aes_ctx );
Gilles Peskinee9a34542019-10-22 20:43:24 +020048 /* Indicate that the entropy nonce length is not set explicitly.
49 * See mbedtls_ctr_drbg_set_nonce_len(). */
50 ctx->reseed_counter = -1;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010051
Gavin Acquroff6aceb512020-03-01 17:06:11 -080052 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020053}
54
Gavin Acquroff6aceb512020-03-01 17:06:11 -080055/*
56 * This function resets CTR_DRBG context to the state immediately
57 * after initial call of mbedtls_ctr_drbg_init().
58 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020059void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
Paul Bakkerfff03662014-06-18 16:21:25 +020060{
61 if( ctx == NULL )
62 return;
63
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010064#if defined(MBEDTLS_THREADING_C)
Gilles Peskineda290f92021-02-09 18:44:02 +010065 /* The mutex is initialized iff f_entropy is set. */
Gilles Peskinef4b34292021-01-30 13:05:32 +010066 if( ctx->f_entropy != NULL )
67 mbedtls_mutex_free( &ctx->mutex );
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010068#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020069 mbedtls_aes_free( &ctx->aes_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050070 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Gavin Acquroff6aceb512020-03-01 17:06:11 -080071 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
72 ctx->reseed_counter = -1;
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;
Joe Subbiania5cb0d22021-08-23 11:35:25 +0100149 MBEDTLS_PUT_UINT32_BE( data_len, p, 0);
150 p += 4 + 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200151 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000152 memcpy( p, data, data_len );
153 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000154
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200155 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000156
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200157 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000158 key[i] = i;
159
Hanno Beckera08651f2018-10-05 09:38:59 +0100160 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key,
161 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300162 {
163 goto exit;
164 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000165
166 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200167 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000168 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200169 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000170 {
171 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200172 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000173 use_len = buf_len;
174
175 while( use_len > 0 )
176 {
Dave Rodgmanffb54992022-11-22 16:40:58 +0000177 mbedtls_xor( chain, chain, p, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200178 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
179 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
180 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000181
Hanno Beckera08651f2018-10-05 09:38:59 +0100182 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
183 chain, chain ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300184 {
185 goto exit;
186 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000187 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200188
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200189 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000190
191 /*
192 * Update IV
193 */
194 buf[3]++;
195 }
196
197 /*
198 * Do final encryption with reduced data
199 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100200 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp,
201 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300202 {
203 goto exit;
204 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200205 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000206 p = output;
207
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200208 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000209 {
Hanno Beckera08651f2018-10-05 09:38:59 +0100210 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
211 iv, iv ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300212 {
213 goto exit;
214 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200215 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
216 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000217 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300218exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200219 mbedtls_aes_free( &aes_ctx );
Dvir Markovich1b364992017-06-26 13:43:34 +0300220 /*
221 * tidy up the stack
222 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500223 mbedtls_platform_zeroize( buf, sizeof( buf ) );
224 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
225 mbedtls_platform_zeroize( key, sizeof( key ) );
226 mbedtls_platform_zeroize( chain, sizeof( chain ) );
Dvir Markovich1b364992017-06-26 13:43:34 +0300227 if( 0 != ret )
228 {
229 /*
230 * wipe partial seed from memory
231 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500232 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
Dvir Markovich1b364992017-06-26 13:43:34 +0300233 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200234
Dvir Markovich1b364992017-06-26 13:43:34 +0300235 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000236}
237
Gilles Peskineed7da592018-08-03 20:16:52 +0200238/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
239 * ctr_drbg_update_internal(ctx, provided_data)
240 * implements
241 * CTR_DRBG_Update(provided_data, Key, V)
242 * with inputs and outputs
243 * ctx->aes_ctx = Key
244 * ctx->counter = V
245 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200246static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
Hanno Beckera08651f2018-10-05 09:38:59 +0100247 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000248{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200249 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000250 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000251 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300252 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000253
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200254 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000255
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200256 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000257 {
258 /*
259 * Increase counter
260 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200261 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000262 if( ++ctx->counter[i - 1] != 0 )
263 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000264
265 /*
266 * Crypt counter block
267 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100268 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
269 ctx->counter, p ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300270 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200271 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300272 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000273
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200274 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000275 }
276
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200277 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000278 tmp[i] ^= data[i];
279
280 /*
281 * Update key and counter
282 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100283 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp,
284 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 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 }
Hanno Beckera08651f2018-10-05 09:38:59 +0100288 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
289 MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000290
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200291exit:
292 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
293 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000294}
295
Gilles Peskineed7da592018-08-03 20:16:52 +0200296/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
TRodziewicz26371e42021-06-08 16:45:41 +0200297 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
Gilles Peskineed7da592018-08-03 20:16:52 +0200298 * implements
299 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
300 * security_strength) -> initial_working_state
301 * with inputs
302 * ctx->counter = all-bits-0
303 * ctx->aes_ctx = context from all-bits-0 key
304 * additional[:add_len] = entropy_input || nonce || personalization_string
305 * and with outputs
306 * ctx = initial_working_state
307 */
TRodziewicz26371e42021-06-08 16:45:41 +0200308int mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
Gilles Peskined9199932018-09-11 16:41:54 +0200309 const unsigned char *additional,
310 size_t add_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000311{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200312 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Janos Follath24eed8d2019-11-22 13:21:35 +0000313 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000314
Gilles Peskined9199932018-09-11 16:41:54 +0200315 if( add_len == 0 )
316 return( 0 );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100317
Gilles Peskined9199932018-09-11 16:41:54 +0200318 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
319 goto exit;
320 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
321 goto exit;
322
323exit:
324 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
325 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000326}
327
Gilles Peskineed7da592018-08-03 20:16:52 +0200328/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
Gilles Peskine9be50982019-10-22 18:42:27 +0200329 * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
Gilles Peskineed7da592018-08-03 20:16:52 +0200330 * implements
331 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
332 * -> new_working_state
333 * with inputs
334 * ctx contains working_state
335 * additional[:len] = additional_input
336 * and entropy_input comes from calling ctx->f_entropy
Gilles Peskine9be50982019-10-22 18:42:27 +0200337 * for (ctx->entropy_len + nonce_len) bytes
Gilles Peskineed7da592018-08-03 20:16:52 +0200338 * and with output
339 * ctx contains new_working_state
340 */
Gilles Peskine97f59ab2019-10-22 18:42:27 +0200341static int mbedtls_ctr_drbg_reseed_internal( mbedtls_ctr_drbg_context *ctx,
342 const unsigned char *additional,
343 size_t len,
344 size_t nonce_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000345{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200346 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000347 size_t seedlen = 0;
Janos Follath24eed8d2019-11-22 13:21:35 +0000348 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000349
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200350 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
351 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Gilles Peskine9be50982019-10-22 18:42:27 +0200352 if( nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
353 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
354 if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200355 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000356
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200357 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000358
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200359 /* Gather entropy_len bytes of entropy to seed state. */
360 if( 0 != ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000361 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200362 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000363 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000364 seedlen += ctx->entropy_len;
365
Gilles Peskine9be50982019-10-22 18:42:27 +0200366 /* Gather entropy for a nonce if requested. */
367 if( nonce_len != 0 )
368 {
ENT\stroej14b919862020-12-23 17:28:33 -0600369 if( 0 != ctx->f_entropy( ctx->p_entropy, seed + seedlen, nonce_len ) )
Gilles Peskine9be50982019-10-22 18:42:27 +0200370 {
371 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
372 }
373 seedlen += nonce_len;
374 }
375
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200376 /* Add additional data if provided. */
377 if( additional != NULL && len != 0 )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000378 {
379 memcpy( seed + seedlen, additional, len );
380 seedlen += len;
381 }
382
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200383 /* Reduce to 384 bits. */
Dvir Markovich1b364992017-06-26 13:43:34 +0300384 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200385 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000386
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200387 /* Update state. */
Dvir Markovich1b364992017-06-26 13:43:34 +0300388 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200389 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000390 ctx->reseed_counter = 1;
391
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200392exit:
393 mbedtls_platform_zeroize( seed, sizeof( seed ) );
394 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000395}
Paul Bakker9af723c2014-05-01 13:03:14 +0200396
Gilles Peskine9be50982019-10-22 18:42:27 +0200397int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
398 const unsigned char *additional, size_t len )
399{
400 return( mbedtls_ctr_drbg_reseed_internal( ctx, additional, len, 0 ) );
401}
402
Gilles Peskinee9a34542019-10-22 20:43:24 +0200403/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
404 * is sufficient to achieve the maximum security strength given the key
405 * size and entropy length. If there is enough entropy in the initial
406 * call to the entropy function to serve as both the entropy input and
407 * the nonce, don't make a second call to get a nonce. */
408static size_t good_nonce_len( size_t entropy_len )
409{
410 if( entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 )
411 return( 0 );
412 else
413 return( ( entropy_len + 1 ) / 2 );
414}
415
Gilles Peskine8bf56132019-10-02 20:31:54 +0200416/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
Gilles Peskine379561f2019-10-18 16:57:48 +0200417 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
Gilles Peskine8bf56132019-10-02 20:31:54 +0200418 * implements
419 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
420 * security_strength) -> initial_working_state
421 * with inputs
422 * custom[:len] = nonce || personalization_string
Gilles Peskine379561f2019-10-18 16:57:48 +0200423 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
Gilles Peskine8bf56132019-10-02 20:31:54 +0200424 * and with outputs
425 * ctx = initial_working_state
426 */
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200427int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
428 int (*f_entropy)(void *, unsigned char *, size_t),
429 void *p_entropy,
430 const unsigned char *custom,
431 size_t len )
Gilles Peskine8bf56132019-10-02 20:31:54 +0200432{
Janos Follath24eed8d2019-11-22 13:21:35 +0000433 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200434 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Gilles Peskinee9a34542019-10-22 20:43:24 +0200435 size_t nonce_len;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200436
437 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
438
Gilles Peskineda290f92021-02-09 18:44:02 +0100439 /* The mutex is initialized iff f_entropy is set. */
Gilles Peskinef4b34292021-01-30 13:05:32 +0100440#if defined(MBEDTLS_THREADING_C)
441 mbedtls_mutex_init( &ctx->mutex );
442#endif
443
Gilles Peskine8bf56132019-10-02 20:31:54 +0200444 ctx->f_entropy = f_entropy;
445 ctx->p_entropy = p_entropy;
446
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200447 if( ctx->entropy_len == 0 )
448 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskinee9a34542019-10-22 20:43:24 +0200449 /* ctx->reseed_counter contains the desired amount of entropy to
450 * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
451 * If it's -1, indicating that the entropy nonce length was not set
452 * explicitly, use a sufficiently large nonce for security. */
453 nonce_len = ( ctx->reseed_counter >= 0 ?
454 (size_t) ctx->reseed_counter :
455 good_nonce_len( ctx->entropy_len ) );
456
Gilles Peskine9be50982019-10-22 18:42:27 +0200457 /* Initialize with an empty key. */
Gilles Peskine8bf56132019-10-02 20:31:54 +0200458 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
459 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
460 {
461 return( ret );
462 }
463
Gilles Peskinee9a34542019-10-22 20:43:24 +0200464 /* Do the initial seeding. */
Gilles Peskine9be50982019-10-22 18:42:27 +0200465 if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len,
Gilles Peskinee9a34542019-10-22 20:43:24 +0200466 nonce_len ) ) != 0 )
Gilles Peskine8bf56132019-10-02 20:31:54 +0200467 {
468 return( ret );
469 }
470 return( 0 );
471}
472
Gilles Peskineed7da592018-08-03 20:16:52 +0200473/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
474 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
475 * implements
476 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
477 * -> working_state_after_reseed
478 * if required, then
479 * CTR_DRBG_Generate(working_state_after_reseed,
480 * requested_number_of_bits, additional_input)
481 * -> status, returned_bits, new_working_state
482 * with inputs
483 * ctx contains working_state
484 * requested_number_of_bits = 8 * output_len
485 * additional[:add_len] = additional_input
486 * and entropy_input comes from calling ctx->f_entropy
487 * and with outputs
488 * status = SUCCESS (this function does the reseed internally)
489 * returned_bits = output[:output_len]
490 * ctx contains new_working_state
491 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200492int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000493 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000494 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000495{
496 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200497 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
498 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000499 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200500 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000501 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000502 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000503
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200504 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
505 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000506
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200507 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
508 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000509
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200510 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000511
512 if( ctx->reseed_counter > ctx->reseed_interval ||
513 ctx->prediction_resistance )
514 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200515 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300516 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000517 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300518 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000519 add_len = 0;
520 }
521
522 if( add_len > 0 )
523 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300524 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200525 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300526 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200527 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000528 }
529
530 while( output_len > 0 )
531 {
532 /*
533 * Increase counter
534 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200535 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000536 if( ++ctx->counter[i - 1] != 0 )
537 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000538
539 /*
540 * Crypt counter block
541 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100542 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
543 ctx->counter, tmp ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300544 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200545 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300546 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000547
Hanno Beckera08651f2018-10-05 09:38:59 +0100548 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE )
549 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000550 /*
551 * Copy random block to destination
552 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000553 memcpy( p, tmp, use_len );
554 p += use_len;
555 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000556 }
557
Dvir Markovich1b364992017-06-26 13:43:34 +0300558 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200559 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000560
561 ctx->reseed_counter++;
562
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200563exit:
564 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
565 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
Gilles Peskineafaee1c2019-11-28 09:45:32 +0100566 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000567}
568
Hanno Beckera08651f2018-10-05 09:38:59 +0100569int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output,
570 size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000571{
Janos Follath24eed8d2019-11-22 13:21:35 +0000572 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100573 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
574
575#if defined(MBEDTLS_THREADING_C)
576 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
577 return( ret );
578#endif
579
580 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
581
582#if defined(MBEDTLS_THREADING_C)
583 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
584 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
585#endif
586
587 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000588}
589
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200590#if defined(MBEDTLS_FS_IO)
Hanno Beckera08651f2018-10-05 09:38:59 +0100591int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx,
592 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000593{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200594 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000595 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200596 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000597
598 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200599 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000600
Gilles Peskineda0913b2022-06-30 17:03:40 +0200601 /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
602 mbedtls_setbuf( f, NULL );
603
Hanno Beckera08651f2018-10-05 09:38:59 +0100604 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf,
605 MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200606 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000607
Hanno Beckera08651f2018-10-05 09:38:59 +0100608 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) !=
609 MBEDTLS_CTR_DRBG_MAX_INPUT )
610 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200611 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Hanno Beckera08651f2018-10-05 09:38:59 +0100612 }
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100613 else
Hanno Beckera08651f2018-10-05 09:38:59 +0100614 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100615 ret = 0;
Hanno Beckera08651f2018-10-05 09:38:59 +0100616 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000617
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100618exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500619 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200620
Paul Bakkerfc754a92011-12-05 13:23:51 +0000621 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200622 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000623}
624
Hanno Beckera08651f2018-10-05 09:38:59 +0100625int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx,
626 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000627{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100628 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200629 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000630 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200631 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200632 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000633
634 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200635 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000636
Gilles Peskineda0913b2022-06-30 17:03:40 +0200637 /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
638 mbedtls_setbuf( f, NULL );
639
Gilles Peskine82204662018-09-11 18:43:09 +0200640 n = fread( buf, 1, sizeof( buf ), f );
641 if( fread( &c, 1, 1, f ) != 0 )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100642 {
Gilles Peskine82204662018-09-11 18:43:09 +0200643 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
644 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100645 }
Gilles Peskine82204662018-09-11 18:43:09 +0200646 if( n == 0 || ferror( f ) )
647 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100648 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200649 goto exit;
650 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000651 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200652 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200653
TRodziewicz26371e42021-06-08 16:45:41 +0200654 ret = mbedtls_ctr_drbg_update( ctx, buf, n );
Gilles Peskine82204662018-09-11 18:43:09 +0200655
656exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500657 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200658 if( f != NULL )
659 fclose( f );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100660 if( ret != 0 )
661 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200662 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000663}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200664#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000665
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200666#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000667
ENT\stroej170f63d02020-12-28 08:50:23 -0600668/* The CTR_DRBG NIST test vectors used here are available at
669 * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip
670 *
671 * The parameters used to derive the test data are:
672 *
673 * [AES-128 use df]
674 * [PredictionResistance = True/False]
675 * [EntropyInputLen = 128]
676 * [NonceLen = 64]
677 * [PersonalizationStringLen = 128]
678 * [AdditionalInputLen = 0]
679 * [ReturnedBitsLen = 512]
680 *
681 * [AES-256 use df]
682 * [PredictionResistance = True/False]
683 * [EntropyInputLen = 256]
684 * [NonceLen = 128]
685 * [PersonalizationStringLen = 256]
686 * [AdditionalInputLen = 0]
687 * [ReturnedBitsLen = 512]
688 *
689 */
690
Gilles Peskine02e79a42019-10-07 17:06:06 +0200691#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
ENT\stroej1df307002020-12-26 12:41:04 -0600692static const unsigned char entropy_source_pr[] =
693 { 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb,
694 0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92,
695 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8,
696 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20,
697 0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0,
698 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad,
699 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200700
ENT\stroej1df307002020-12-26 12:41:04 -0600701static const unsigned char entropy_source_nopr[] =
702 { 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45,
703 0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9,
704 0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20,
705 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f,
706 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c };
707
stroebeljcd4de1b52021-01-04 18:14:32 -0600708static const unsigned char pers_pr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600709 { 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a,
710 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad };
711
stroebeljcd4de1b52021-01-04 18:14:32 -0600712static const unsigned char pers_nopr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600713 { 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c,
714 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f };
715
716static const unsigned char result_pr[] =
717 { 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66,
718 0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff,
719 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10,
720 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30,
721 0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4,
722 0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc,
723 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06,
724 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf };
725
726static const unsigned char result_nopr[] =
727 { 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13,
728 0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0,
729 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf,
730 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2,
731 0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7,
732 0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2,
733 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02,
734 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200735#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000736
ENT\stroej1df307002020-12-26 12:41:04 -0600737static const unsigned char entropy_source_pr[] =
738 { 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49,
739 0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a,
740 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85,
741 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e,
742 0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15,
743 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45,
744 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8,
745 0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c,
746 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3,
747 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce,
748 0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e,
749 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76,
750 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77,
751 0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe };
752
753static const unsigned char entropy_source_nopr[] =
754 { 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d,
755 0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0,
756 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73,
757 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c,
758 0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2,
759 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1,
760 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a,
761 0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb,
762 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a,
763 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 };
764
stroebeljcd4de1b52021-01-04 18:14:32 -0600765static const unsigned char pers_pr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600766 { 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33,
767 0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e,
768 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0,
769 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 };
770
stroebeljcd4de1b52021-01-04 18:14:32 -0600771static const unsigned char pers_nopr[] =
ENT\stroej1df307002020-12-26 12:41:04 -0600772 { 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29,
773 0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf,
774 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb,
775 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b };
776
777static const unsigned char result_pr[] =
778 { 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85,
779 0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d,
780 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62,
781 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d,
782 0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb,
783 0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39,
784 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40,
785 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 };
786
787static const unsigned char result_nopr[] =
788 { 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad,
789 0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3,
790 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b,
791 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14,
792 0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54,
793 0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30,
794 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a,
795 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200796#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000797
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100798static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200799static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
800 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000801{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100802 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000803 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100804 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000805 return( 0 );
806}
807
Paul Bakker7dc4c442014-02-01 22:50:26 +0100808#define CHK( c ) if( (c) != 0 ) \
809 { \
810 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200811 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100812 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100813 }
814
bootstrap-prime6dbbf442022-05-17 19:30:44 -0400815#define SELF_TEST_OUTPUT_DISCARD_LENGTH 64
stroebeljcd4de1b52021-01-04 18:14:32 -0600816
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000817/*
818 * Checkup routine
819 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200820int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000821{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200822 mbedtls_ctr_drbg_context ctx;
stroebeljcd4de1b52021-01-04 18:14:32 -0600823 unsigned char buf[ sizeof( result_pr ) ];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000824
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200825 mbedtls_ctr_drbg_init( &ctx );
826
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000827 /*
828 * Based on a NIST CTR_DRBG test vector (PR = True)
829 */
830 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200831 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000832
833 test_offset = 0;
ENT\stroej1df307002020-12-26 12:41:04 -0600834 mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE );
stroebeljcd4de1b52021-01-04 18:14:32 -0600835 mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200836 CHK( mbedtls_ctr_drbg_seed( &ctx,
837 ctr_drbg_self_test_entropy,
838 (void *) entropy_source_pr,
stroebeljcd4de1b52021-01-04 18:14:32 -0600839 pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200840 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
bootstrap-prime6dbbf442022-05-17 19:30:44 -0400841 CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH ) );
stroebeljcd4de1b52021-01-04 18:14:32 -0600842 CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_pr ) ) );
843 CHK( memcmp( buf, result_pr, sizeof( result_pr ) ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000844
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100845 mbedtls_ctr_drbg_free( &ctx );
846
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000847 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200848 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000849
850 /*
851 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
852 */
853 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200854 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000855
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100856 mbedtls_ctr_drbg_init( &ctx );
857
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000858 test_offset = 0;
ENT\stroej1df307002020-12-26 12:41:04 -0600859 mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
stroebeljcd4de1b52021-01-04 18:14:32 -0600860 mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200861 CHK( mbedtls_ctr_drbg_seed( &ctx,
862 ctr_drbg_self_test_entropy,
863 (void *) entropy_source_nopr,
stroebeljcd4de1b52021-01-04 18:14:32 -0600864 pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200865 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
bootstrap-prime6dbbf442022-05-17 19:30:44 -0400866 CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH ) );
stroebeljcd4de1b52021-01-04 18:14:32 -0600867 CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_nopr ) ) );
868 CHK( memcmp( buf, result_nopr, sizeof( result_nopr ) ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000869
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100870 mbedtls_ctr_drbg_free( &ctx );
871
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000872 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200873 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000874
875 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200876 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000877
878 return( 0 );
879}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200880#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000881
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200882#endif /* MBEDTLS_CTR_DRBG_C */