blob: 7872e9b2d5800ebf62968c4ff24602c82a5e5333 [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
Gilles Peskinedb09ef62020-06-03 01:43:33 +020027#include "common.h"
Paul Bakker0e04d0e2011-11-27 14:46:59 +000028
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020029#if defined(MBEDTLS_CTR_DRBG_C)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000030
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000031#include "mbedtls/ctr_drbg.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050032#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000033#include "mbedtls/error.h"
Paul Bakker0e04d0e2011-11-27 14:46:59 +000034
Rich Evans00ab4702015-02-06 13:43:58 +000035#include <string.h>
36
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020037#if defined(MBEDTLS_FS_IO)
Paul Bakkerfc754a92011-12-05 13:23:51 +000038#include <stdio.h>
39#endif
40
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#if defined(MBEDTLS_SELF_TEST)
42#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000043#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010044#else
Rich Evans00ab4702015-02-06 13:43:58 +000045#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020046#define mbedtls_printf printf
47#endif /* MBEDTLS_PLATFORM_C */
48#endif /* MBEDTLS_SELF_TEST */
Paul Bakker7dc4c442014-02-01 22:50:26 +010049
Paul Bakker18d32912011-12-10 21:42:49 +000050/*
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020051 * CTR_DRBG context initialization
52 */
53void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
54{
55 memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
Gilles Peskinee9a34542019-10-22 20:43:24 +020056 /* Indicate that the entropy nonce length is not set explicitly.
57 * See mbedtls_ctr_drbg_set_nonce_len(). */
58 ctx->reseed_counter = -1;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010059
60#if defined(MBEDTLS_THREADING_C)
61 mbedtls_mutex_init( &ctx->mutex );
62#endif
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020063}
64
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020065void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
Paul Bakkerfff03662014-06-18 16:21:25 +020066{
67 if( ctx == NULL )
68 return;
69
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010070#if defined(MBEDTLS_THREADING_C)
71 mbedtls_mutex_free( &ctx->mutex );
72#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020073 mbedtls_aes_free( &ctx->aes_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050074 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Paul Bakkerfff03662014-06-18 16:21:25 +020075}
76
Hanno Beckera08651f2018-10-05 09:38:59 +010077void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx,
78 int resistance )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000079{
80 ctx->prediction_resistance = resistance;
81}
82
Hanno Beckera08651f2018-10-05 09:38:59 +010083void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx,
84 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000085{
86 ctx->entropy_len = len;
87}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +020088
Gilles Peskine9be50982019-10-22 18:42:27 +020089int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx,
90 size_t len )
91{
92 /* If mbedtls_ctr_drbg_seed() has already been called, it's
93 * too late. Return the error code that's closest to making sense. */
94 if( ctx->f_entropy != NULL )
95 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
96
97 if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
98 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
99#if SIZE_MAX > INT_MAX
100 /* This shouldn't be an issue because
101 * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible
102 * configuration, but make sure anyway. */
103 if( len > INT_MAX )
104 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
105#endif
106
107 /* For backward compatibility with Mbed TLS <= 2.19, store the
108 * entropy nonce length in a field that already exists, but isn't
109 * used until after the initial seeding. */
110 /* Due to the capping of len above, the value fits in an int. */
111 ctx->reseed_counter = (int) len;
112 return( 0 );
113}
114
Hanno Beckera08651f2018-10-05 09:38:59 +0100115void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx,
116 int interval )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000117{
118 ctx->reseed_interval = interval;
119}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200120
121static int block_cipher_df( unsigned char *output,
122 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000123{
Hanno Beckera08651f2018-10-05 09:38:59 +0100124 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
125 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200126 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
127 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
128 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100129 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200130 mbedtls_aes_context aes_ctx;
Dvir Markovich1b364992017-06-26 13:43:34 +0300131 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000132
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200133 int i, j;
134 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000135
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200136 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
137 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100138
Hanno Beckera08651f2018-10-05 09:38:59 +0100139 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
140 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200141 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000142
143 /*
144 * Construct IV (16 bytes) and S in buffer
145 * IV = Counter (in 32-bits) padded to 16 with zeroes
146 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
147 * data || 0x80
148 * (Total is padded to a multiple of 16-bytes with zeroes)
149 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200150 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000151 *p++ = ( data_len >> 24 ) & 0xff;
152 *p++ = ( data_len >> 16 ) & 0xff;
153 *p++ = ( data_len >> 8 ) & 0xff;
154 *p++ = ( data_len ) & 0xff;
155 p += 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200156 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000157 memcpy( p, data, data_len );
158 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000159
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200160 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000161
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200162 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000163 key[i] = i;
164
Hanno Beckera08651f2018-10-05 09:38:59 +0100165 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key,
166 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300167 {
168 goto exit;
169 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000170
171 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200172 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000173 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200174 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000175 {
176 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200177 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000178 use_len = buf_len;
179
180 while( use_len > 0 )
181 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200182 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000183 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200184 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
185 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
186 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000187
Hanno Beckera08651f2018-10-05 09:38:59 +0100188 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
189 chain, chain ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300190 {
191 goto exit;
192 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000193 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200194
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200195 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000196
197 /*
198 * Update IV
199 */
200 buf[3]++;
201 }
202
203 /*
204 * Do final encryption with reduced data
205 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100206 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp,
207 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300208 {
209 goto exit;
210 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200211 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000212 p = output;
213
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200214 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000215 {
Hanno Beckera08651f2018-10-05 09:38:59 +0100216 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
217 iv, iv ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300218 {
219 goto exit;
220 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200221 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
222 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000223 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300224exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200225 mbedtls_aes_free( &aes_ctx );
Dvir Markovich1b364992017-06-26 13:43:34 +0300226 /*
227 * tidy up the stack
228 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500229 mbedtls_platform_zeroize( buf, sizeof( buf ) );
230 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
231 mbedtls_platform_zeroize( key, sizeof( key ) );
232 mbedtls_platform_zeroize( chain, sizeof( chain ) );
Dvir Markovich1b364992017-06-26 13:43:34 +0300233 if( 0 != ret )
234 {
235 /*
236 * wipe partial seed from memory
237 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500238 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
Dvir Markovich1b364992017-06-26 13:43:34 +0300239 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200240
Dvir Markovich1b364992017-06-26 13:43:34 +0300241 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000242}
243
Gilles Peskineed7da592018-08-03 20:16:52 +0200244/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
245 * ctr_drbg_update_internal(ctx, provided_data)
246 * implements
247 * CTR_DRBG_Update(provided_data, Key, V)
248 * with inputs and outputs
249 * ctx->aes_ctx = Key
250 * ctx->counter = V
251 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200252static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
Hanno Beckera08651f2018-10-05 09:38:59 +0100253 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000254{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200255 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000256 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000257 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300258 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000259
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200260 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000261
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200262 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000263 {
264 /*
265 * Increase counter
266 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200267 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000268 if( ++ctx->counter[i - 1] != 0 )
269 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000270
271 /*
272 * Crypt counter block
273 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100274 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
275 ctx->counter, p ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300276 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200277 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300278 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000279
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200280 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000281 }
282
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200283 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000284 tmp[i] ^= data[i];
285
286 /*
287 * Update key and counter
288 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100289 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp,
290 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300291 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200292 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300293 }
Hanno Beckera08651f2018-10-05 09:38:59 +0100294 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
295 MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000296
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200297exit:
298 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
299 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000300}
301
Gilles Peskineed7da592018-08-03 20:16:52 +0200302/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
303 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
304 * implements
305 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
306 * security_strength) -> initial_working_state
307 * with inputs
308 * ctx->counter = all-bits-0
309 * ctx->aes_ctx = context from all-bits-0 key
310 * additional[:add_len] = entropy_input || nonce || personalization_string
311 * and with outputs
312 * ctx = initial_working_state
313 */
Gilles Peskined9199932018-09-11 16:41:54 +0200314int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
315 const unsigned char *additional,
316 size_t add_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000317{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200318 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Janos Follath24eed8d2019-11-22 13:21:35 +0000319 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000320
Gilles Peskined9199932018-09-11 16:41:54 +0200321 if( add_len == 0 )
322 return( 0 );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100323
Gilles Peskined9199932018-09-11 16:41:54 +0200324 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
325 goto exit;
326 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
327 goto exit;
328
329exit:
330 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
331 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000332}
333
Gilles Peskined9199932018-09-11 16:41:54 +0200334#if !defined(MBEDTLS_DEPRECATED_REMOVED)
335void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
336 const unsigned char *additional,
337 size_t add_len )
338{
339 /* MAX_INPUT would be more logical here, but we have to match
340 * block_cipher_df()'s limits since we can't propagate errors */
341 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
342 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
343 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
344}
345#endif /* MBEDTLS_DEPRECATED_REMOVED */
346
Gilles Peskineed7da592018-08-03 20:16:52 +0200347/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
Gilles Peskine9be50982019-10-22 18:42:27 +0200348 * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
Gilles Peskineed7da592018-08-03 20:16:52 +0200349 * implements
350 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
351 * -> new_working_state
352 * with inputs
353 * ctx contains working_state
354 * additional[:len] = additional_input
355 * and entropy_input comes from calling ctx->f_entropy
Gilles Peskine9be50982019-10-22 18:42:27 +0200356 * for (ctx->entropy_len + nonce_len) bytes
Gilles Peskineed7da592018-08-03 20:16:52 +0200357 * and with output
358 * ctx contains new_working_state
359 */
Gilles Peskine97f59ab2019-10-22 18:42:27 +0200360static int mbedtls_ctr_drbg_reseed_internal( mbedtls_ctr_drbg_context *ctx,
361 const unsigned char *additional,
362 size_t len,
363 size_t nonce_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000364{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200365 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000366 size_t seedlen = 0;
Janos Follath24eed8d2019-11-22 13:21:35 +0000367 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000368
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200369 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
370 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Gilles Peskine9be50982019-10-22 18:42:27 +0200371 if( nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
372 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
373 if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200374 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000375
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200376 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000377
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200378 /* Gather entropy_len bytes of entropy to seed state. */
379 if( 0 != ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000380 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200381 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000382 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000383 seedlen += ctx->entropy_len;
384
Gilles Peskine9be50982019-10-22 18:42:27 +0200385 /* Gather entropy for a nonce if requested. */
386 if( nonce_len != 0 )
387 {
388 if( 0 != ctx->f_entropy( ctx->p_entropy, seed, nonce_len ) )
389 {
390 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
391 }
392 seedlen += nonce_len;
393 }
394
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200395 /* Add additional data if provided. */
396 if( additional != NULL && len != 0 )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000397 {
398 memcpy( seed + seedlen, additional, len );
399 seedlen += len;
400 }
401
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200402 /* Reduce to 384 bits. */
Dvir Markovich1b364992017-06-26 13:43:34 +0300403 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200404 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000405
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200406 /* Update state. */
Dvir Markovich1b364992017-06-26 13:43:34 +0300407 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200408 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000409 ctx->reseed_counter = 1;
410
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200411exit:
412 mbedtls_platform_zeroize( seed, sizeof( seed ) );
413 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000414}
Paul Bakker9af723c2014-05-01 13:03:14 +0200415
Gilles Peskine9be50982019-10-22 18:42:27 +0200416int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
417 const unsigned char *additional, size_t len )
418{
419 return( mbedtls_ctr_drbg_reseed_internal( ctx, additional, len, 0 ) );
420}
421
Gilles Peskinee9a34542019-10-22 20:43:24 +0200422/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
423 * is sufficient to achieve the maximum security strength given the key
424 * size and entropy length. If there is enough entropy in the initial
425 * call to the entropy function to serve as both the entropy input and
426 * the nonce, don't make a second call to get a nonce. */
427static size_t good_nonce_len( size_t entropy_len )
428{
429 if( entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 )
430 return( 0 );
431 else
432 return( ( entropy_len + 1 ) / 2 );
433}
434
Gilles Peskine8bf56132019-10-02 20:31:54 +0200435/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
Gilles Peskine379561f2019-10-18 16:57:48 +0200436 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
Gilles Peskine8bf56132019-10-02 20:31:54 +0200437 * implements
438 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
439 * security_strength) -> initial_working_state
440 * with inputs
441 * custom[:len] = nonce || personalization_string
Gilles Peskine379561f2019-10-18 16:57:48 +0200442 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
Gilles Peskine8bf56132019-10-02 20:31:54 +0200443 * and with outputs
444 * ctx = initial_working_state
445 */
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200446int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
447 int (*f_entropy)(void *, unsigned char *, size_t),
448 void *p_entropy,
449 const unsigned char *custom,
450 size_t len )
Gilles Peskine8bf56132019-10-02 20:31:54 +0200451{
Janos Follath24eed8d2019-11-22 13:21:35 +0000452 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200453 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Gilles Peskinee9a34542019-10-22 20:43:24 +0200454 size_t nonce_len;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200455
456 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
457
458 mbedtls_aes_init( &ctx->aes_ctx );
459
460 ctx->f_entropy = f_entropy;
461 ctx->p_entropy = p_entropy;
462
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200463 if( ctx->entropy_len == 0 )
464 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskinee9a34542019-10-22 20:43:24 +0200465 /* ctx->reseed_counter contains the desired amount of entropy to
466 * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
467 * If it's -1, indicating that the entropy nonce length was not set
468 * explicitly, use a sufficiently large nonce for security. */
469 nonce_len = ( ctx->reseed_counter >= 0 ?
470 (size_t) ctx->reseed_counter :
471 good_nonce_len( ctx->entropy_len ) );
472
Gilles Peskine8bf56132019-10-02 20:31:54 +0200473 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
474
Gilles Peskine9be50982019-10-22 18:42:27 +0200475 /* Initialize with an empty key. */
Gilles Peskine8bf56132019-10-02 20:31:54 +0200476 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
477 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
478 {
479 return( ret );
480 }
481
Gilles Peskinee9a34542019-10-22 20:43:24 +0200482 /* Do the initial seeding. */
Gilles Peskine9be50982019-10-22 18:42:27 +0200483 if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len,
Gilles Peskinee9a34542019-10-22 20:43:24 +0200484 nonce_len ) ) != 0 )
Gilles Peskine8bf56132019-10-02 20:31:54 +0200485 {
486 return( ret );
487 }
488 return( 0 );
489}
490
Gilles Peskineed7da592018-08-03 20:16:52 +0200491/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
492 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
493 * implements
494 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
495 * -> working_state_after_reseed
496 * if required, then
497 * CTR_DRBG_Generate(working_state_after_reseed,
498 * requested_number_of_bits, additional_input)
499 * -> status, returned_bits, new_working_state
500 * with inputs
501 * ctx contains working_state
502 * requested_number_of_bits = 8 * output_len
503 * additional[:add_len] = additional_input
504 * and entropy_input comes from calling ctx->f_entropy
505 * and with outputs
506 * status = SUCCESS (this function does the reseed internally)
507 * returned_bits = output[:output_len]
508 * ctx contains new_working_state
509 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200510int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000511 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000512 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000513{
514 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200515 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
516 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000517 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200518 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000519 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000520 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000521
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200522 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
523 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000524
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200525 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
526 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000527
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200528 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000529
530 if( ctx->reseed_counter > ctx->reseed_interval ||
531 ctx->prediction_resistance )
532 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200533 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300534 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000535 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300536 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000537 add_len = 0;
538 }
539
540 if( add_len > 0 )
541 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300542 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200543 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300544 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200545 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000546 }
547
548 while( output_len > 0 )
549 {
550 /*
551 * Increase counter
552 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200553 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000554 if( ++ctx->counter[i - 1] != 0 )
555 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000556
557 /*
558 * Crypt counter block
559 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100560 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
561 ctx->counter, tmp ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300562 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200563 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300564 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000565
Hanno Beckera08651f2018-10-05 09:38:59 +0100566 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE )
567 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000568 /*
569 * Copy random block to destination
570 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000571 memcpy( p, tmp, use_len );
572 p += use_len;
573 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000574 }
575
Dvir Markovich1b364992017-06-26 13:43:34 +0300576 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200577 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000578
579 ctx->reseed_counter++;
580
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200581exit:
582 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
583 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
Gilles Peskineafaee1c2019-11-28 09:45:32 +0100584 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000585}
586
Hanno Beckera08651f2018-10-05 09:38:59 +0100587int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output,
588 size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000589{
Janos Follath24eed8d2019-11-22 13:21:35 +0000590 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100591 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
592
593#if defined(MBEDTLS_THREADING_C)
594 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
595 return( ret );
596#endif
597
598 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
599
600#if defined(MBEDTLS_THREADING_C)
601 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
602 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
603#endif
604
605 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000606}
607
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200608#if defined(MBEDTLS_FS_IO)
Hanno Beckera08651f2018-10-05 09:38:59 +0100609int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx,
610 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000611{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200612 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000613 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200614 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000615
616 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200617 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000618
Hanno Beckera08651f2018-10-05 09:38:59 +0100619 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf,
620 MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200621 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000622
Hanno Beckera08651f2018-10-05 09:38:59 +0100623 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) !=
624 MBEDTLS_CTR_DRBG_MAX_INPUT )
625 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200626 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Hanno Beckera08651f2018-10-05 09:38:59 +0100627 }
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100628 else
Hanno Beckera08651f2018-10-05 09:38:59 +0100629 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100630 ret = 0;
Hanno Beckera08651f2018-10-05 09:38:59 +0100631 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000632
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100633exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500634 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200635
Paul Bakkerfc754a92011-12-05 13:23:51 +0000636 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200637 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000638}
639
Hanno Beckera08651f2018-10-05 09:38:59 +0100640int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx,
641 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000642{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100643 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200644 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000645 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200646 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200647 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000648
649 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200650 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000651
Gilles Peskine82204662018-09-11 18:43:09 +0200652 n = fread( buf, 1, sizeof( buf ), f );
653 if( fread( &c, 1, 1, f ) != 0 )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100654 {
Gilles Peskine82204662018-09-11 18:43:09 +0200655 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
656 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100657 }
Gilles Peskine82204662018-09-11 18:43:09 +0200658 if( n == 0 || ferror( f ) )
659 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100660 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200661 goto exit;
662 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000663 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200664 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200665
Gilles Peskine82204662018-09-11 18:43:09 +0200666 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
667
668exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500669 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200670 if( f != NULL )
671 fclose( f );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100672 if( ret != 0 )
673 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200674 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000675}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200676#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000677
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200678#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000679
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000680static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000681 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
682 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
683 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
684 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
685 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
686 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
687 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
688 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
689 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
690 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
691 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
692 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
693
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000694static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000695 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
696 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
697 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
698 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
699 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
700 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
701 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
702 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
703
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100704static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000705 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
706 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
707
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100708static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000709 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
710 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
711
Gilles Peskine02e79a42019-10-07 17:06:06 +0200712#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
713static const unsigned char result_pr[16] =
714 { 0x95, 0x3c, 0xa5, 0xbd, 0x44, 0x1, 0x34, 0xb7,
715 0x13, 0x58, 0x3e, 0x6a, 0x6c, 0x7e, 0x88, 0x8a };
716
717static const unsigned char result_nopr[16] =
718 { 0x6c, 0x25, 0x27, 0x95, 0xa3, 0x62, 0xd6, 0xdb,
719 0x90, 0xfd, 0x69, 0xb5, 0x42, 0x9, 0x4b, 0x84 };
720#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100721static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000722 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
723 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
724
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100725static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000726 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
727 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200728#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000729
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100730static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200731static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
732 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000733{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100734 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000735 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100736 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000737 return( 0 );
738}
739
Paul Bakker7dc4c442014-02-01 22:50:26 +0100740#define CHK( c ) if( (c) != 0 ) \
741 { \
742 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200743 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100744 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100745 }
746
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000747/*
748 * Checkup routine
749 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200750int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000751{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200752 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000753 unsigned char buf[16];
754
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200755 mbedtls_ctr_drbg_init( &ctx );
756
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000757 /*
758 * Based on a NIST CTR_DRBG test vector (PR = True)
759 */
760 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200761 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000762
763 test_offset = 0;
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200764 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
Gilles Peskine0ed378a2019-10-22 20:33:56 +0200765 mbedtls_ctr_drbg_set_nonce_len( &ctx, 0 );
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200766 CHK( mbedtls_ctr_drbg_seed( &ctx,
767 ctr_drbg_self_test_entropy,
768 (void *) entropy_source_pr,
769 nonce_pers_pr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200770 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
771 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
772 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
773 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000774
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100775 mbedtls_ctr_drbg_free( &ctx );
776
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000777 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200778 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000779
780 /*
781 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
782 */
783 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200784 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000785
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100786 mbedtls_ctr_drbg_init( &ctx );
787
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000788 test_offset = 0;
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200789 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
Gilles Peskine0ed378a2019-10-22 20:33:56 +0200790 mbedtls_ctr_drbg_set_nonce_len( &ctx, 0 );
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200791 CHK( mbedtls_ctr_drbg_seed( &ctx,
792 ctr_drbg_self_test_entropy,
793 (void *) entropy_source_nopr,
794 nonce_pers_nopr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200795 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
796 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
797 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100798 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000799
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100800 mbedtls_ctr_drbg_free( &ctx );
801
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000802 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200803 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000804
805 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200806 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000807
808 return( 0 );
809}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200810#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000811
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200812#endif /* MBEDTLS_CTR_DRBG_C */