blob: 517b4558039e41d10cc69744769335496746e7f3 [file] [log] [blame]
Paul Bakker0e04d0e2011-11-27 14:46:59 +00001/*
2 * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
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 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000020 */
21/*
Paul Sokolovsky8d6d8c82018-02-10 11:11:41 +020022 * The NIST SP 800-90 DRBGs are described in the following publication.
Paul Bakker0e04d0e2011-11-27 14:46:59 +000023 *
24 * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
25 */
26
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020027#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000028#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020029#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020030#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020031#endif
Paul Bakker0e04d0e2011-11-27 14:46:59 +000032
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020033#if defined(MBEDTLS_CTR_DRBG_C)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000034
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000035#include "mbedtls/ctr_drbg.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050036#include "mbedtls/platform_util.h"
Paul Bakker0e04d0e2011-11-27 14:46:59 +000037
Rich Evans00ab4702015-02-06 13:43:58 +000038#include <string.h>
39
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020040#if defined(MBEDTLS_FS_IO)
Paul Bakkerfc754a92011-12-05 13:23:51 +000041#include <stdio.h>
42#endif
43
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if defined(MBEDTLS_SELF_TEST)
45#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010047#else
Rich Evans00ab4702015-02-06 13:43:58 +000048#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020049#define mbedtls_printf printf
50#endif /* MBEDTLS_PLATFORM_C */
51#endif /* MBEDTLS_SELF_TEST */
Paul Bakker7dc4c442014-02-01 22:50:26 +010052
Paul Bakker18d32912011-12-10 21:42:49 +000053/*
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020054 * CTR_DRBG context initialization
55 */
56void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
57{
58 memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
Gilles Peskinee9a34542019-10-22 20:43:24 +020059 /* Indicate that the entropy nonce length is not set explicitly.
60 * See mbedtls_ctr_drbg_set_nonce_len(). */
61 ctx->reseed_counter = -1;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010062
63#if defined(MBEDTLS_THREADING_C)
64 mbedtls_mutex_init( &ctx->mutex );
65#endif
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020066}
67
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020068void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
Paul Bakkerfff03662014-06-18 16:21:25 +020069{
70 if( ctx == NULL )
71 return;
72
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010073#if defined(MBEDTLS_THREADING_C)
74 mbedtls_mutex_free( &ctx->mutex );
75#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020076 mbedtls_aes_free( &ctx->aes_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050077 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Paul Bakkerfff03662014-06-18 16:21:25 +020078}
79
Hanno Beckera08651f2018-10-05 09:38:59 +010080void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx,
81 int resistance )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000082{
83 ctx->prediction_resistance = resistance;
84}
85
Hanno Beckera08651f2018-10-05 09:38:59 +010086void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx,
87 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000088{
89 ctx->entropy_len = len;
90}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +020091
Gilles Peskine9be50982019-10-22 18:42:27 +020092int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx,
93 size_t len )
94{
95 /* If mbedtls_ctr_drbg_seed() has already been called, it's
96 * too late. Return the error code that's closest to making sense. */
97 if( ctx->f_entropy != NULL )
98 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
99
100 if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
101 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
102#if SIZE_MAX > INT_MAX
103 /* This shouldn't be an issue because
104 * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible
105 * configuration, but make sure anyway. */
106 if( len > INT_MAX )
107 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
108#endif
109
110 /* For backward compatibility with Mbed TLS <= 2.19, store the
111 * entropy nonce length in a field that already exists, but isn't
112 * used until after the initial seeding. */
113 /* Due to the capping of len above, the value fits in an int. */
114 ctx->reseed_counter = (int) len;
115 return( 0 );
116}
117
Hanno Beckera08651f2018-10-05 09:38:59 +0100118void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx,
119 int interval )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000120{
121 ctx->reseed_interval = interval;
122}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200123
124static int block_cipher_df( unsigned char *output,
125 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000126{
Hanno Beckera08651f2018-10-05 09:38:59 +0100127 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
128 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200129 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
130 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
131 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100132 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200133 mbedtls_aes_context aes_ctx;
Dvir Markovich1b364992017-06-26 13:43:34 +0300134 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000135
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200136 int i, j;
137 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000138
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200139 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
140 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100141
Hanno Beckera08651f2018-10-05 09:38:59 +0100142 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
143 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200144 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000145
146 /*
147 * Construct IV (16 bytes) and S in buffer
148 * IV = Counter (in 32-bits) padded to 16 with zeroes
149 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
150 * data || 0x80
151 * (Total is padded to a multiple of 16-bytes with zeroes)
152 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200153 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000154 *p++ = ( data_len >> 24 ) & 0xff;
155 *p++ = ( data_len >> 16 ) & 0xff;
156 *p++ = ( data_len >> 8 ) & 0xff;
157 *p++ = ( data_len ) & 0xff;
158 p += 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200159 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000160 memcpy( p, data, data_len );
161 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000162
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200163 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000164
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200165 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000166 key[i] = i;
167
Hanno Beckera08651f2018-10-05 09:38:59 +0100168 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key,
169 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300170 {
171 goto exit;
172 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000173
174 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200175 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000176 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200177 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000178 {
179 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200180 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000181 use_len = buf_len;
182
183 while( use_len > 0 )
184 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200185 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000186 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200187 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
188 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
189 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000190
Hanno Beckera08651f2018-10-05 09:38:59 +0100191 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
192 chain, chain ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300193 {
194 goto exit;
195 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000196 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200197
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200198 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000199
200 /*
201 * Update IV
202 */
203 buf[3]++;
204 }
205
206 /*
207 * Do final encryption with reduced data
208 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100209 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp,
210 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300211 {
212 goto exit;
213 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200214 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000215 p = output;
216
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200217 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000218 {
Hanno Beckera08651f2018-10-05 09:38:59 +0100219 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
220 iv, iv ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300221 {
222 goto exit;
223 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200224 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
225 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000226 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300227exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200228 mbedtls_aes_free( &aes_ctx );
Dvir Markovich1b364992017-06-26 13:43:34 +0300229 /*
230 * tidy up the stack
231 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500232 mbedtls_platform_zeroize( buf, sizeof( buf ) );
233 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
234 mbedtls_platform_zeroize( key, sizeof( key ) );
235 mbedtls_platform_zeroize( chain, sizeof( chain ) );
Dvir Markovich1b364992017-06-26 13:43:34 +0300236 if( 0 != ret )
237 {
238 /*
239 * wipe partial seed from memory
240 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500241 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
Dvir Markovich1b364992017-06-26 13:43:34 +0300242 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200243
Dvir Markovich1b364992017-06-26 13:43:34 +0300244 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000245}
246
Gilles Peskineed7da592018-08-03 20:16:52 +0200247/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
248 * ctr_drbg_update_internal(ctx, provided_data)
249 * implements
250 * CTR_DRBG_Update(provided_data, Key, V)
251 * with inputs and outputs
252 * ctx->aes_ctx = Key
253 * ctx->counter = V
254 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200255static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
Hanno Beckera08651f2018-10-05 09:38:59 +0100256 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000257{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200258 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000259 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000260 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300261 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000262
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200263 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000264
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200265 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000266 {
267 /*
268 * Increase counter
269 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200270 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000271 if( ++ctx->counter[i - 1] != 0 )
272 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000273
274 /*
275 * Crypt counter block
276 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100277 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
278 ctx->counter, p ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300279 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200280 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300281 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000282
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200283 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000284 }
285
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200286 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000287 tmp[i] ^= data[i];
288
289 /*
290 * Update key and counter
291 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100292 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp,
293 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300294 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200295 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300296 }
Hanno Beckera08651f2018-10-05 09:38:59 +0100297 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
298 MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000299
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200300exit:
301 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
302 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000303}
304
Gilles Peskineed7da592018-08-03 20:16:52 +0200305/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
306 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
307 * implements
308 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
309 * security_strength) -> initial_working_state
310 * with inputs
311 * ctx->counter = all-bits-0
312 * ctx->aes_ctx = context from all-bits-0 key
313 * additional[:add_len] = entropy_input || nonce || personalization_string
314 * and with outputs
315 * ctx = initial_working_state
316 */
Gilles Peskined9199932018-09-11 16:41:54 +0200317int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
318 const unsigned char *additional,
319 size_t add_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000320{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200321 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Gilles Peskined9199932018-09-11 16:41:54 +0200322 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000323
Gilles Peskined9199932018-09-11 16:41:54 +0200324 if( add_len == 0 )
325 return( 0 );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100326
Gilles Peskined9199932018-09-11 16:41:54 +0200327 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
328 goto exit;
329 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
330 goto exit;
331
332exit:
333 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
334 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000335}
336
Gilles Peskined9199932018-09-11 16:41:54 +0200337#if !defined(MBEDTLS_DEPRECATED_REMOVED)
338void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
339 const unsigned char *additional,
340 size_t add_len )
341{
342 /* MAX_INPUT would be more logical here, but we have to match
343 * block_cipher_df()'s limits since we can't propagate errors */
344 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
345 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
346 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
347}
348#endif /* MBEDTLS_DEPRECATED_REMOVED */
349
Gilles Peskineed7da592018-08-03 20:16:52 +0200350/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
Gilles Peskine9be50982019-10-22 18:42:27 +0200351 * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
Gilles Peskineed7da592018-08-03 20:16:52 +0200352 * implements
353 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
354 * -> new_working_state
355 * with inputs
356 * ctx contains working_state
357 * additional[:len] = additional_input
358 * and entropy_input comes from calling ctx->f_entropy
Gilles Peskine9be50982019-10-22 18:42:27 +0200359 * for (ctx->entropy_len + nonce_len) bytes
Gilles Peskineed7da592018-08-03 20:16:52 +0200360 * and with output
361 * ctx contains new_working_state
362 */
Gilles Peskine97f59ab2019-10-22 18:42:27 +0200363static int mbedtls_ctr_drbg_reseed_internal( mbedtls_ctr_drbg_context *ctx,
364 const unsigned char *additional,
365 size_t len,
366 size_t nonce_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000367{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200368 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000369 size_t seedlen = 0;
Dvir Markovich1b364992017-06-26 13:43:34 +0300370 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000371
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200372 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
373 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Gilles Peskine9be50982019-10-22 18:42:27 +0200374 if( nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
375 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
376 if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200377 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000378
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200379 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000380
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200381 /* Gather entropy_len bytes of entropy to seed state. */
382 if( 0 != ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000383 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200384 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000385 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000386 seedlen += ctx->entropy_len;
387
Gilles Peskine9be50982019-10-22 18:42:27 +0200388 /* Gather entropy for a nonce if requested. */
389 if( nonce_len != 0 )
390 {
391 if( 0 != ctx->f_entropy( ctx->p_entropy, seed, nonce_len ) )
392 {
393 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
394 }
395 seedlen += nonce_len;
396 }
397
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200398 /* Add additional data if provided. */
399 if( additional != NULL && len != 0 )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000400 {
401 memcpy( seed + seedlen, additional, len );
402 seedlen += len;
403 }
404
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200405 /* Reduce to 384 bits. */
Dvir Markovich1b364992017-06-26 13:43:34 +0300406 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200407 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000408
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200409 /* Update state. */
Dvir Markovich1b364992017-06-26 13:43:34 +0300410 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200411 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000412 ctx->reseed_counter = 1;
413
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200414exit:
415 mbedtls_platform_zeroize( seed, sizeof( seed ) );
416 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000417}
Paul Bakker9af723c2014-05-01 13:03:14 +0200418
Gilles Peskine9be50982019-10-22 18:42:27 +0200419int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
420 const unsigned char *additional, size_t len )
421{
422 return( mbedtls_ctr_drbg_reseed_internal( ctx, additional, len, 0 ) );
423}
424
Gilles Peskinee9a34542019-10-22 20:43:24 +0200425/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
426 * is sufficient to achieve the maximum security strength given the key
427 * size and entropy length. If there is enough entropy in the initial
428 * call to the entropy function to serve as both the entropy input and
429 * the nonce, don't make a second call to get a nonce. */
430static size_t good_nonce_len( size_t entropy_len )
431{
432 if( entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 )
433 return( 0 );
434 else
435 return( ( entropy_len + 1 ) / 2 );
436}
437
Gilles Peskine8bf56132019-10-02 20:31:54 +0200438/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
Gilles Peskine379561f2019-10-18 16:57:48 +0200439 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
Gilles Peskine8bf56132019-10-02 20:31:54 +0200440 * implements
441 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
442 * security_strength) -> initial_working_state
443 * with inputs
444 * custom[:len] = nonce || personalization_string
Gilles Peskine379561f2019-10-18 16:57:48 +0200445 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
Gilles Peskine8bf56132019-10-02 20:31:54 +0200446 * and with outputs
447 * ctx = initial_working_state
448 */
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200449int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
450 int (*f_entropy)(void *, unsigned char *, size_t),
451 void *p_entropy,
452 const unsigned char *custom,
453 size_t len )
Gilles Peskine8bf56132019-10-02 20:31:54 +0200454{
455 int ret;
456 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Gilles Peskinee9a34542019-10-22 20:43:24 +0200457 size_t nonce_len;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200458
459 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
460
461 mbedtls_aes_init( &ctx->aes_ctx );
462
463 ctx->f_entropy = f_entropy;
464 ctx->p_entropy = p_entropy;
465
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200466 if( ctx->entropy_len == 0 )
467 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskinee9a34542019-10-22 20:43:24 +0200468 /* ctx->reseed_counter contains the desired amount of entropy to
469 * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
470 * If it's -1, indicating that the entropy nonce length was not set
471 * explicitly, use a sufficiently large nonce for security. */
472 nonce_len = ( ctx->reseed_counter >= 0 ?
473 (size_t) ctx->reseed_counter :
474 good_nonce_len( ctx->entropy_len ) );
475
Gilles Peskine8bf56132019-10-02 20:31:54 +0200476 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
477
Gilles Peskine9be50982019-10-22 18:42:27 +0200478 /* Initialize with an empty key. */
Gilles Peskine8bf56132019-10-02 20:31:54 +0200479 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
480 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
481 {
482 return( ret );
483 }
484
Gilles Peskinee9a34542019-10-22 20:43:24 +0200485 /* Do the initial seeding. */
Gilles Peskine9be50982019-10-22 18:42:27 +0200486 if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len,
Gilles Peskinee9a34542019-10-22 20:43:24 +0200487 nonce_len ) ) != 0 )
Gilles Peskine8bf56132019-10-02 20:31:54 +0200488 {
489 return( ret );
490 }
491 return( 0 );
492}
493
Gilles Peskineed7da592018-08-03 20:16:52 +0200494/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
495 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
496 * implements
497 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
498 * -> working_state_after_reseed
499 * if required, then
500 * CTR_DRBG_Generate(working_state_after_reseed,
501 * requested_number_of_bits, additional_input)
502 * -> status, returned_bits, new_working_state
503 * with inputs
504 * ctx contains working_state
505 * requested_number_of_bits = 8 * output_len
506 * additional[:add_len] = additional_input
507 * and entropy_input comes from calling ctx->f_entropy
508 * and with outputs
509 * status = SUCCESS (this function does the reseed internally)
510 * returned_bits = output[:output_len]
511 * ctx contains new_working_state
512 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200513int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000514 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000515 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000516{
517 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200518 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
519 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000520 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200521 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000522 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000523 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000524
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200525 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
526 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000527
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200528 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
529 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000530
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200531 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000532
533 if( ctx->reseed_counter > ctx->reseed_interval ||
534 ctx->prediction_resistance )
535 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200536 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300537 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000538 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300539 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000540 add_len = 0;
541 }
542
543 if( add_len > 0 )
544 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300545 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200546 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300547 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200548 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000549 }
550
551 while( output_len > 0 )
552 {
553 /*
554 * Increase counter
555 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200556 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000557 if( ++ctx->counter[i - 1] != 0 )
558 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000559
560 /*
561 * Crypt counter block
562 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100563 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
564 ctx->counter, tmp ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300565 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200566 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300567 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000568
Hanno Beckera08651f2018-10-05 09:38:59 +0100569 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE )
570 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000571 /*
572 * Copy random block to destination
573 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000574 memcpy( p, tmp, use_len );
575 p += use_len;
576 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000577 }
578
Dvir Markovich1b364992017-06-26 13:43:34 +0300579 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200580 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000581
582 ctx->reseed_counter++;
583
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200584exit:
585 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
586 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
Gilles Peskineafaee1c2019-11-28 09:45:32 +0100587 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000588}
589
Hanno Beckera08651f2018-10-05 09:38:59 +0100590int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output,
591 size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000592{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100593 int ret;
594 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
595
596#if defined(MBEDTLS_THREADING_C)
597 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
598 return( ret );
599#endif
600
601 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
602
603#if defined(MBEDTLS_THREADING_C)
604 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
605 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
606#endif
607
608 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000609}
610
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200611#if defined(MBEDTLS_FS_IO)
Hanno Beckera08651f2018-10-05 09:38:59 +0100612int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx,
613 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000614{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200615 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000616 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200617 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000618
619 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200620 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000621
Hanno Beckera08651f2018-10-05 09:38:59 +0100622 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf,
623 MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200624 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000625
Hanno Beckera08651f2018-10-05 09:38:59 +0100626 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) !=
627 MBEDTLS_CTR_DRBG_MAX_INPUT )
628 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200629 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Hanno Beckera08651f2018-10-05 09:38:59 +0100630 }
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100631 else
Hanno Beckera08651f2018-10-05 09:38:59 +0100632 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100633 ret = 0;
Hanno Beckera08651f2018-10-05 09:38:59 +0100634 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000635
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100636exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500637 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200638
Paul Bakkerfc754a92011-12-05 13:23:51 +0000639 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200640 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000641}
642
Hanno Beckera08651f2018-10-05 09:38:59 +0100643int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx,
644 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000645{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100646 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200647 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000648 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200649 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200650 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000651
652 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200653 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000654
Gilles Peskine82204662018-09-11 18:43:09 +0200655 n = fread( buf, 1, sizeof( buf ), f );
656 if( fread( &c, 1, 1, f ) != 0 )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100657 {
Gilles Peskine82204662018-09-11 18:43:09 +0200658 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
659 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100660 }
Gilles Peskine82204662018-09-11 18:43:09 +0200661 if( n == 0 || ferror( f ) )
662 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100663 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200664 goto exit;
665 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000666 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200667 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200668
Gilles Peskine82204662018-09-11 18:43:09 +0200669 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
670
671exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500672 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200673 if( f != NULL )
674 fclose( f );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100675 if( ret != 0 )
676 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200677 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000678}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200679#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000680
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200681#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000682
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000683static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000684 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
685 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
686 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
687 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
688 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
689 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
690 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
691 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
692 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
693 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
694 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
695 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
696
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000697static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000698 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
699 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
700 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
701 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
702 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
703 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
704 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
705 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
706
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100707static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000708 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
709 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
710
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100711static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000712 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
713 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
714
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100715static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000716 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
717 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
718
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100719static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000720 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
721 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
722
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100723static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200724static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
725 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000726{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100727 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000728 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100729 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000730 return( 0 );
731}
732
Paul Bakker7dc4c442014-02-01 22:50:26 +0100733#define CHK( c ) if( (c) != 0 ) \
734 { \
735 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200736 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100737 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100738 }
739
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000740/*
741 * Checkup routine
742 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200743int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000744{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200745 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000746 unsigned char buf[16];
747
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200748 mbedtls_ctr_drbg_init( &ctx );
749
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000750 /*
751 * Based on a NIST CTR_DRBG test vector (PR = True)
752 */
753 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200754 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000755
756 test_offset = 0;
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200757 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
Gilles Peskine0ed378a2019-10-22 20:33:56 +0200758 mbedtls_ctr_drbg_set_nonce_len( &ctx, 0 );
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200759 CHK( mbedtls_ctr_drbg_seed( &ctx,
760 ctr_drbg_self_test_entropy,
761 (void *) entropy_source_pr,
762 nonce_pers_pr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200763 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
764 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
765 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
766 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000767
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100768 mbedtls_ctr_drbg_free( &ctx );
769
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000770 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200771 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000772
773 /*
774 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
775 */
776 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200777 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000778
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100779 mbedtls_ctr_drbg_init( &ctx );
780
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000781 test_offset = 0;
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200782 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
Gilles Peskine0ed378a2019-10-22 20:33:56 +0200783 mbedtls_ctr_drbg_set_nonce_len( &ctx, 0 );
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200784 CHK( mbedtls_ctr_drbg_seed( &ctx,
785 ctr_drbg_self_test_entropy,
786 (void *) entropy_source_nopr,
787 nonce_pers_nopr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200788 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
789 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
790 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100791 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000792
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100793 mbedtls_ctr_drbg_free( &ctx );
794
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000795 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200796 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000797
798 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200799 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000800
801 return( 0 );
802}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200803#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000804
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200805#endif /* MBEDTLS_CTR_DRBG_C */