blob: 281dc4fe1d66ad0a63f15d4c77defbcda382a79e [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"
Janos Follath24eed8d2019-11-22 13:21:35 +000037#include "mbedtls/error.h"
Paul Bakker0e04d0e2011-11-27 14:46:59 +000038
Rich Evans00ab4702015-02-06 13:43:58 +000039#include <string.h>
40
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#if defined(MBEDTLS_FS_IO)
Paul Bakkerfc754a92011-12-05 13:23:51 +000042#include <stdio.h>
43#endif
44
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020045#if defined(MBEDTLS_SELF_TEST)
46#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000047#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010048#else
Rich Evans00ab4702015-02-06 13:43:58 +000049#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020050#define mbedtls_printf printf
51#endif /* MBEDTLS_PLATFORM_C */
52#endif /* MBEDTLS_SELF_TEST */
Paul Bakker7dc4c442014-02-01 22:50:26 +010053
Paul Bakker18d32912011-12-10 21:42:49 +000054/*
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020055 * CTR_DRBG context initialization
56 */
57void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
58{
59 memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
Gilles Peskinee9a34542019-10-22 20:43:24 +020060 /* Indicate that the entropy nonce length is not set explicitly.
61 * See mbedtls_ctr_drbg_set_nonce_len(). */
62 ctx->reseed_counter = -1;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010063
64#if defined(MBEDTLS_THREADING_C)
65 mbedtls_mutex_init( &ctx->mutex );
66#endif
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020067}
68
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020069void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
Paul Bakkerfff03662014-06-18 16:21:25 +020070{
71 if( ctx == NULL )
72 return;
73
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010074#if defined(MBEDTLS_THREADING_C)
75 mbedtls_mutex_free( &ctx->mutex );
76#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020077 mbedtls_aes_free( &ctx->aes_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050078 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Paul Bakkerfff03662014-06-18 16:21:25 +020079}
80
Hanno Beckera08651f2018-10-05 09:38:59 +010081void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx,
82 int resistance )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000083{
84 ctx->prediction_resistance = resistance;
85}
86
Hanno Beckera08651f2018-10-05 09:38:59 +010087void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx,
88 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000089{
90 ctx->entropy_len = len;
91}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +020092
Gilles Peskine9be50982019-10-22 18:42:27 +020093int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx,
94 size_t len )
95{
96 /* If mbedtls_ctr_drbg_seed() has already been called, it's
97 * too late. Return the error code that's closest to making sense. */
98 if( ctx->f_entropy != NULL )
99 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
100
101 if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
102 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
103#if SIZE_MAX > INT_MAX
104 /* This shouldn't be an issue because
105 * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible
106 * configuration, but make sure anyway. */
107 if( len > INT_MAX )
108 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
109#endif
110
111 /* For backward compatibility with Mbed TLS <= 2.19, store the
112 * entropy nonce length in a field that already exists, but isn't
113 * used until after the initial seeding. */
114 /* Due to the capping of len above, the value fits in an int. */
115 ctx->reseed_counter = (int) len;
116 return( 0 );
117}
118
Hanno Beckera08651f2018-10-05 09:38:59 +0100119void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx,
120 int interval )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000121{
122 ctx->reseed_interval = interval;
123}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200124
125static int block_cipher_df( unsigned char *output,
126 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000127{
Hanno Beckera08651f2018-10-05 09:38:59 +0100128 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
129 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200130 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
131 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
132 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100133 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200134 mbedtls_aes_context aes_ctx;
Dvir Markovich1b364992017-06-26 13:43:34 +0300135 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000136
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200137 int i, j;
138 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000139
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200140 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
141 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100142
Hanno Beckera08651f2018-10-05 09:38:59 +0100143 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
144 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200145 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000146
147 /*
148 * Construct IV (16 bytes) and S in buffer
149 * IV = Counter (in 32-bits) padded to 16 with zeroes
150 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
151 * data || 0x80
152 * (Total is padded to a multiple of 16-bytes with zeroes)
153 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200154 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000155 *p++ = ( data_len >> 24 ) & 0xff;
156 *p++ = ( data_len >> 16 ) & 0xff;
157 *p++ = ( data_len >> 8 ) & 0xff;
158 *p++ = ( data_len ) & 0xff;
159 p += 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200160 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000161 memcpy( p, data, data_len );
162 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000163
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200164 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000165
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200166 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000167 key[i] = i;
168
Hanno Beckera08651f2018-10-05 09:38:59 +0100169 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key,
170 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300171 {
172 goto exit;
173 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000174
175 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200176 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000177 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200178 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000179 {
180 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200181 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000182 use_len = buf_len;
183
184 while( use_len > 0 )
185 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200186 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000187 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200188 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
189 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
190 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000191
Hanno Beckera08651f2018-10-05 09:38:59 +0100192 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
193 chain, chain ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300194 {
195 goto exit;
196 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000197 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200198
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200199 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000200
201 /*
202 * Update IV
203 */
204 buf[3]++;
205 }
206
207 /*
208 * Do final encryption with reduced data
209 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100210 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp,
211 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300212 {
213 goto exit;
214 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200215 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000216 p = output;
217
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200218 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000219 {
Hanno Beckera08651f2018-10-05 09:38:59 +0100220 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
221 iv, iv ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300222 {
223 goto exit;
224 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200225 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
226 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000227 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300228exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200229 mbedtls_aes_free( &aes_ctx );
Dvir Markovich1b364992017-06-26 13:43:34 +0300230 /*
231 * tidy up the stack
232 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500233 mbedtls_platform_zeroize( buf, sizeof( buf ) );
234 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
235 mbedtls_platform_zeroize( key, sizeof( key ) );
236 mbedtls_platform_zeroize( chain, sizeof( chain ) );
Dvir Markovich1b364992017-06-26 13:43:34 +0300237 if( 0 != ret )
238 {
239 /*
240 * wipe partial seed from memory
241 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500242 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
Dvir Markovich1b364992017-06-26 13:43:34 +0300243 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200244
Dvir Markovich1b364992017-06-26 13:43:34 +0300245 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000246}
247
Gilles Peskineed7da592018-08-03 20:16:52 +0200248/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
249 * ctr_drbg_update_internal(ctx, provided_data)
250 * implements
251 * CTR_DRBG_Update(provided_data, Key, V)
252 * with inputs and outputs
253 * ctx->aes_ctx = Key
254 * ctx->counter = V
255 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200256static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
Hanno Beckera08651f2018-10-05 09:38:59 +0100257 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000258{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200259 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000260 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000261 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300262 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000263
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200264 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000265
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200266 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000267 {
268 /*
269 * Increase counter
270 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200271 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000272 if( ++ctx->counter[i - 1] != 0 )
273 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000274
275 /*
276 * Crypt counter block
277 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100278 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
279 ctx->counter, p ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300280 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200281 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300282 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000283
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200284 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000285 }
286
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200287 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000288 tmp[i] ^= data[i];
289
290 /*
291 * Update key and counter
292 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100293 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp,
294 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300295 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200296 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300297 }
Hanno Beckera08651f2018-10-05 09:38:59 +0100298 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
299 MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000300
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200301exit:
302 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
303 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000304}
305
Gilles Peskineed7da592018-08-03 20:16:52 +0200306/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
307 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
308 * implements
309 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
310 * security_strength) -> initial_working_state
311 * with inputs
312 * ctx->counter = all-bits-0
313 * ctx->aes_ctx = context from all-bits-0 key
314 * additional[:add_len] = entropy_input || nonce || personalization_string
315 * and with outputs
316 * ctx = initial_working_state
317 */
Gilles Peskined9199932018-09-11 16:41:54 +0200318int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
319 const unsigned char *additional,
320 size_t add_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000321{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200322 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Janos Follath24eed8d2019-11-22 13:21:35 +0000323 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000324
Gilles Peskined9199932018-09-11 16:41:54 +0200325 if( add_len == 0 )
326 return( 0 );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100327
Gilles Peskined9199932018-09-11 16:41:54 +0200328 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
329 goto exit;
330 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
331 goto exit;
332
333exit:
334 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
335 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000336}
337
Gilles Peskined9199932018-09-11 16:41:54 +0200338#if !defined(MBEDTLS_DEPRECATED_REMOVED)
339void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
340 const unsigned char *additional,
341 size_t add_len )
342{
343 /* MAX_INPUT would be more logical here, but we have to match
344 * block_cipher_df()'s limits since we can't propagate errors */
345 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
346 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
347 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
348}
349#endif /* MBEDTLS_DEPRECATED_REMOVED */
350
Gilles Peskineed7da592018-08-03 20:16:52 +0200351/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
Gilles Peskine9be50982019-10-22 18:42:27 +0200352 * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
Gilles Peskineed7da592018-08-03 20:16:52 +0200353 * implements
354 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
355 * -> new_working_state
356 * with inputs
357 * ctx contains working_state
358 * additional[:len] = additional_input
359 * and entropy_input comes from calling ctx->f_entropy
Gilles Peskine9be50982019-10-22 18:42:27 +0200360 * for (ctx->entropy_len + nonce_len) bytes
Gilles Peskineed7da592018-08-03 20:16:52 +0200361 * and with output
362 * ctx contains new_working_state
363 */
Gilles Peskine97f59ab2019-10-22 18:42:27 +0200364static int mbedtls_ctr_drbg_reseed_internal( mbedtls_ctr_drbg_context *ctx,
365 const unsigned char *additional,
366 size_t len,
367 size_t nonce_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000368{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200369 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000370 size_t seedlen = 0;
Janos Follath24eed8d2019-11-22 13:21:35 +0000371 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000372
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200373 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
374 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Gilles Peskine9be50982019-10-22 18:42:27 +0200375 if( nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
376 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
377 if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200378 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000379
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200380 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000381
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200382 /* Gather entropy_len bytes of entropy to seed state. */
383 if( 0 != ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000384 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200385 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000386 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000387 seedlen += ctx->entropy_len;
388
Gilles Peskine9be50982019-10-22 18:42:27 +0200389 /* Gather entropy for a nonce if requested. */
390 if( nonce_len != 0 )
391 {
392 if( 0 != ctx->f_entropy( ctx->p_entropy, seed, nonce_len ) )
393 {
394 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
395 }
396 seedlen += nonce_len;
397 }
398
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200399 /* Add additional data if provided. */
400 if( additional != NULL && len != 0 )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000401 {
402 memcpy( seed + seedlen, additional, len );
403 seedlen += len;
404 }
405
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200406 /* Reduce to 384 bits. */
Dvir Markovich1b364992017-06-26 13:43:34 +0300407 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200408 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000409
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200410 /* Update state. */
Dvir Markovich1b364992017-06-26 13:43:34 +0300411 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200412 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000413 ctx->reseed_counter = 1;
414
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200415exit:
416 mbedtls_platform_zeroize( seed, sizeof( seed ) );
417 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000418}
Paul Bakker9af723c2014-05-01 13:03:14 +0200419
Gilles Peskine9be50982019-10-22 18:42:27 +0200420int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
421 const unsigned char *additional, size_t len )
422{
423 return( mbedtls_ctr_drbg_reseed_internal( ctx, additional, len, 0 ) );
424}
425
Gilles Peskinee9a34542019-10-22 20:43:24 +0200426/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
427 * is sufficient to achieve the maximum security strength given the key
428 * size and entropy length. If there is enough entropy in the initial
429 * call to the entropy function to serve as both the entropy input and
430 * the nonce, don't make a second call to get a nonce. */
431static size_t good_nonce_len( size_t entropy_len )
432{
433 if( entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 )
434 return( 0 );
435 else
436 return( ( entropy_len + 1 ) / 2 );
437}
438
Gilles Peskine8bf56132019-10-02 20:31:54 +0200439/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
Gilles Peskine379561f2019-10-18 16:57:48 +0200440 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
Gilles Peskine8bf56132019-10-02 20:31:54 +0200441 * implements
442 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
443 * security_strength) -> initial_working_state
444 * with inputs
445 * custom[:len] = nonce || personalization_string
Gilles Peskine379561f2019-10-18 16:57:48 +0200446 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
Gilles Peskine8bf56132019-10-02 20:31:54 +0200447 * and with outputs
448 * ctx = initial_working_state
449 */
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200450int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
451 int (*f_entropy)(void *, unsigned char *, size_t),
452 void *p_entropy,
453 const unsigned char *custom,
454 size_t len )
Gilles Peskine8bf56132019-10-02 20:31:54 +0200455{
Janos Follath24eed8d2019-11-22 13:21:35 +0000456 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200457 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Gilles Peskinee9a34542019-10-22 20:43:24 +0200458 size_t nonce_len;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200459
460 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
461
462 mbedtls_aes_init( &ctx->aes_ctx );
463
464 ctx->f_entropy = f_entropy;
465 ctx->p_entropy = p_entropy;
466
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200467 if( ctx->entropy_len == 0 )
468 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskinee9a34542019-10-22 20:43:24 +0200469 /* ctx->reseed_counter contains the desired amount of entropy to
470 * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
471 * If it's -1, indicating that the entropy nonce length was not set
472 * explicitly, use a sufficiently large nonce for security. */
473 nonce_len = ( ctx->reseed_counter >= 0 ?
474 (size_t) ctx->reseed_counter :
475 good_nonce_len( ctx->entropy_len ) );
476
Gilles Peskine8bf56132019-10-02 20:31:54 +0200477 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
478
Gilles Peskine9be50982019-10-22 18:42:27 +0200479 /* Initialize with an empty key. */
Gilles Peskine8bf56132019-10-02 20:31:54 +0200480 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
481 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
482 {
483 return( ret );
484 }
485
Gilles Peskinee9a34542019-10-22 20:43:24 +0200486 /* Do the initial seeding. */
Gilles Peskine9be50982019-10-22 18:42:27 +0200487 if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len,
Gilles Peskinee9a34542019-10-22 20:43:24 +0200488 nonce_len ) ) != 0 )
Gilles Peskine8bf56132019-10-02 20:31:54 +0200489 {
490 return( ret );
491 }
492 return( 0 );
493}
494
Gilles Peskineed7da592018-08-03 20:16:52 +0200495/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
496 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
497 * implements
498 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
499 * -> working_state_after_reseed
500 * if required, then
501 * CTR_DRBG_Generate(working_state_after_reseed,
502 * requested_number_of_bits, additional_input)
503 * -> status, returned_bits, new_working_state
504 * with inputs
505 * ctx contains working_state
506 * requested_number_of_bits = 8 * output_len
507 * additional[:add_len] = additional_input
508 * and entropy_input comes from calling ctx->f_entropy
509 * and with outputs
510 * status = SUCCESS (this function does the reseed internally)
511 * returned_bits = output[:output_len]
512 * ctx contains new_working_state
513 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200514int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000515 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000516 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000517{
518 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200519 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
520 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000521 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200522 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000523 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000524 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000525
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200526 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
527 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000528
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200529 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
530 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000531
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200532 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000533
534 if( ctx->reseed_counter > ctx->reseed_interval ||
535 ctx->prediction_resistance )
536 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200537 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300538 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000539 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300540 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000541 add_len = 0;
542 }
543
544 if( add_len > 0 )
545 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300546 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200547 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300548 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200549 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000550 }
551
552 while( output_len > 0 )
553 {
554 /*
555 * Increase counter
556 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200557 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000558 if( ++ctx->counter[i - 1] != 0 )
559 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000560
561 /*
562 * Crypt counter block
563 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100564 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
565 ctx->counter, tmp ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300566 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200567 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300568 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000569
Hanno Beckera08651f2018-10-05 09:38:59 +0100570 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE )
571 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000572 /*
573 * Copy random block to destination
574 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000575 memcpy( p, tmp, use_len );
576 p += use_len;
577 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000578 }
579
Dvir Markovich1b364992017-06-26 13:43:34 +0300580 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200581 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000582
583 ctx->reseed_counter++;
584
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200585exit:
586 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
587 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000588 return( 0 );
589}
590
Hanno Beckera08651f2018-10-05 09:38:59 +0100591int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output,
592 size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000593{
Janos Follath24eed8d2019-11-22 13:21:35 +0000594 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100595 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
596
597#if defined(MBEDTLS_THREADING_C)
598 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
599 return( ret );
600#endif
601
602 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
603
604#if defined(MBEDTLS_THREADING_C)
605 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
606 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
607#endif
608
609 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000610}
611
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200612#if defined(MBEDTLS_FS_IO)
Hanno Beckera08651f2018-10-05 09:38:59 +0100613int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx,
614 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000615{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200616 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000617 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200618 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000619
620 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200621 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000622
Hanno Beckera08651f2018-10-05 09:38:59 +0100623 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf,
624 MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200625 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000626
Hanno Beckera08651f2018-10-05 09:38:59 +0100627 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) !=
628 MBEDTLS_CTR_DRBG_MAX_INPUT )
629 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200630 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Hanno Beckera08651f2018-10-05 09:38:59 +0100631 }
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100632 else
Hanno Beckera08651f2018-10-05 09:38:59 +0100633 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100634 ret = 0;
Hanno Beckera08651f2018-10-05 09:38:59 +0100635 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000636
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100637exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500638 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200639
Paul Bakkerfc754a92011-12-05 13:23:51 +0000640 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200641 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000642}
643
Hanno Beckera08651f2018-10-05 09:38:59 +0100644int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx,
645 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000646{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100647 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200648 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000649 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200650 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200651 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000652
653 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200654 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000655
Gilles Peskine82204662018-09-11 18:43:09 +0200656 n = fread( buf, 1, sizeof( buf ), f );
657 if( fread( &c, 1, 1, f ) != 0 )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100658 {
Gilles Peskine82204662018-09-11 18:43:09 +0200659 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
660 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100661 }
Gilles Peskine82204662018-09-11 18:43:09 +0200662 if( n == 0 || ferror( f ) )
663 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100664 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200665 goto exit;
666 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000667 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200668 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200669
Gilles Peskine82204662018-09-11 18:43:09 +0200670 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
671
672exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500673 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200674 if( f != NULL )
675 fclose( f );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100676 if( ret != 0 )
677 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200678 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000679}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200680#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000681
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200682#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000683
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000684static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000685 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
686 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
687 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
688 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
689 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
690 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
691 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
692 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
693 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
694 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
695 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
696 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
697
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000698static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000699 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
700 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
701 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
702 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
703 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
704 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
705 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
706 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
707
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100708static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000709 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
710 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
711
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100712static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000713 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
714 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
715
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100716static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000717 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
718 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
719
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100720static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000721 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
722 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
723
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100724static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200725static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
726 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000727{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100728 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000729 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100730 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000731 return( 0 );
732}
733
Paul Bakker7dc4c442014-02-01 22:50:26 +0100734#define CHK( c ) if( (c) != 0 ) \
735 { \
736 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200737 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100738 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100739 }
740
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000741/*
742 * Checkup routine
743 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200744int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000745{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200746 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000747 unsigned char buf[16];
748
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200749 mbedtls_ctr_drbg_init( &ctx );
750
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000751 /*
752 * Based on a NIST CTR_DRBG test vector (PR = True)
753 */
754 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200755 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000756
757 test_offset = 0;
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200758 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
Gilles Peskine0ed378a2019-10-22 20:33:56 +0200759 mbedtls_ctr_drbg_set_nonce_len( &ctx, 0 );
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200760 CHK( mbedtls_ctr_drbg_seed( &ctx,
761 ctr_drbg_self_test_entropy,
762 (void *) entropy_source_pr,
763 nonce_pers_pr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200764 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
765 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
766 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
767 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000768
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100769 mbedtls_ctr_drbg_free( &ctx );
770
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000771 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200772 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000773
774 /*
775 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
776 */
777 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200778 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000779
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100780 mbedtls_ctr_drbg_init( &ctx );
781
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000782 test_offset = 0;
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200783 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
Gilles Peskine0ed378a2019-10-22 20:33:56 +0200784 mbedtls_ctr_drbg_set_nonce_len( &ctx, 0 );
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200785 CHK( mbedtls_ctr_drbg_seed( &ctx,
786 ctr_drbg_self_test_entropy,
787 (void *) entropy_source_nopr,
788 nonce_pers_nopr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200789 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
790 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
791 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100792 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000793
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100794 mbedtls_ctr_drbg_free( &ctx );
795
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000796 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200797 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000798
799 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200800 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000801
802 return( 0 );
803}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200804#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000805
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200806#endif /* MBEDTLS_CTR_DRBG_C */