blob: e92008bbe86f755f45bc75e7475efc8b957e3fd9 [file] [log] [blame]
Paul Bakker0e04d0e2011-11-27 14:46:59 +00001/*
2 * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
3 *
Bence Szépkútia2947ac2020-08-19 16:37:36 +02004 * Copyright The Mbed TLS Contributors
Bence Szépkútif744bd72020-06-05 13:02:18 +02005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6 *
7 * This file is provided under the Apache License 2.0, or the
8 * GNU General Public License v2.0 or later.
9 *
10 * **********
11 * Apache License 2.0:
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +020012 *
13 * Licensed under the Apache License, Version 2.0 (the "License"); you may
14 * not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 * http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
21 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
Paul Bakker0e04d0e2011-11-27 14:46:59 +000024 *
Bence Szépkútif744bd72020-06-05 13:02:18 +020025 * **********
26 *
27 * **********
28 * GNU General Public License v2.0 or later:
29 *
30 * This program is free software; you can redistribute it and/or modify
31 * it under the terms of the GNU General Public License as published by
32 * the Free Software Foundation; either version 2 of the License, or
33 * (at your option) any later version.
34 *
35 * This program is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
39 *
40 * You should have received a copy of the GNU General Public License along
41 * with this program; if not, write to the Free Software Foundation, Inc.,
42 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
43 *
44 * **********
Paul Bakker0e04d0e2011-11-27 14:46:59 +000045 */
46/*
Paul Sokolovsky8d6d8c82018-02-10 11:11:41 +020047 * The NIST SP 800-90 DRBGs are described in the following publication.
Paul Bakker0e04d0e2011-11-27 14:46:59 +000048 *
49 * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
50 */
51
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020052#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000053#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020054#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020055#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020056#endif
Paul Bakker0e04d0e2011-11-27 14:46:59 +000057
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020058#if defined(MBEDTLS_CTR_DRBG_C)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000059
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000060#include "mbedtls/ctr_drbg.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050061#include "mbedtls/platform_util.h"
Paul Bakker0e04d0e2011-11-27 14:46:59 +000062
Rich Evans00ab4702015-02-06 13:43:58 +000063#include <string.h>
64
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020065#if defined(MBEDTLS_FS_IO)
Paul Bakkerfc754a92011-12-05 13:23:51 +000066#include <stdio.h>
67#endif
68
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020069#if defined(MBEDTLS_SELF_TEST)
70#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000071#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010072#else
Rich Evans00ab4702015-02-06 13:43:58 +000073#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020074#define mbedtls_printf printf
75#endif /* MBEDTLS_PLATFORM_C */
76#endif /* MBEDTLS_SELF_TEST */
Paul Bakker7dc4c442014-02-01 22:50:26 +010077
Paul Bakker18d32912011-12-10 21:42:49 +000078/*
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020079 * CTR_DRBG context initialization
80 */
81void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
82{
83 memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010084
Gavin Acquroff77cb30c2020-03-01 17:06:11 -080085 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
86
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010087#if defined(MBEDTLS_THREADING_C)
88 mbedtls_mutex_init( &ctx->mutex );
89#endif
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020090}
91
Gavin Acquroff77cb30c2020-03-01 17:06:11 -080092/*
93 * This function resets CTR_DRBG context to the state immediately
94 * after initial call of mbedtls_ctr_drbg_init().
95 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020096void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
Paul Bakkerfff03662014-06-18 16:21:25 +020097{
98 if( ctx == NULL )
99 return;
100
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100101#if defined(MBEDTLS_THREADING_C)
102 mbedtls_mutex_free( &ctx->mutex );
103#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200104 mbedtls_aes_free( &ctx->aes_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500105 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Gavin Acquroff77cb30c2020-03-01 17:06:11 -0800106 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
107#if defined(MBEDTLS_THREADING_C)
108 mbedtls_mutex_init( &ctx->mutex );
109#endif
Paul Bakkerfff03662014-06-18 16:21:25 +0200110}
111
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200112void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000113{
114 ctx->prediction_resistance = resistance;
115}
116
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200117void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000118{
119 ctx->entropy_len = len;
120}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200121
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200122void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000123{
124 ctx->reseed_interval = interval;
125}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200126
127static int block_cipher_df( unsigned char *output,
128 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000129{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200130 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
131 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
132 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
133 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100134 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200135 mbedtls_aes_context aes_ctx;
Dvir Markovich1b364992017-06-26 13:43:34 +0300136 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000137
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200138 int i, j;
139 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000140
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200141 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
142 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100143
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200144 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
145 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
Dvir Markovich1b364992017-06-26 13:43:34 +0300169 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
170 {
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
Dvir Markovich1b364992017-06-26 13:43:34 +0300191 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ) ) != 0 )
192 {
193 goto exit;
194 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000195 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200196
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200197 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000198
199 /*
200 * Update IV
201 */
202 buf[3]++;
203 }
204
205 /*
206 * Do final encryption with reduced data
207 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300208 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
209 {
210 goto exit;
211 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200212 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000213 p = output;
214
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200215 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000216 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300217 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) ) != 0 )
218 {
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,
253 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 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300274 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200275 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000276
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200277 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000278 }
279
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200280 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000281 tmp[i] ^= data[i];
282
283 /*
284 * Update key and counter
285 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300286 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200287 goto exit;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200288 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000289
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200290exit:
291 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
292 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000293}
294
Gilles Peskineed7da592018-08-03 20:16:52 +0200295/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
296 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
297 * implements
298 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
299 * security_strength) -> initial_working_state
300 * with inputs
301 * ctx->counter = all-bits-0
302 * ctx->aes_ctx = context from all-bits-0 key
303 * additional[:add_len] = entropy_input || nonce || personalization_string
304 * and with outputs
305 * ctx = initial_working_state
306 */
Gilles Peskined9199932018-09-11 16:41:54 +0200307int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
308 const unsigned char *additional,
309 size_t add_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000310{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200311 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Gilles Peskined9199932018-09-11 16:41:54 +0200312 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000313
Gilles Peskined9199932018-09-11 16:41:54 +0200314 if( add_len == 0 )
315 return( 0 );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100316
Gilles Peskined9199932018-09-11 16:41:54 +0200317 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
318 goto exit;
319 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
320 goto exit;
321
322exit:
323 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
324 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000325}
326
Gilles Peskined9199932018-09-11 16:41:54 +0200327#if !defined(MBEDTLS_DEPRECATED_REMOVED)
328void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
329 const unsigned char *additional,
330 size_t add_len )
331{
332 /* MAX_INPUT would be more logical here, but we have to match
333 * block_cipher_df()'s limits since we can't propagate errors */
334 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
335 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
336 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
337}
338#endif /* MBEDTLS_DEPRECATED_REMOVED */
339
Gilles Peskineed7da592018-08-03 20:16:52 +0200340/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
341 * mbedtls_ctr_drbg_reseed(ctx, additional, len)
342 * implements
343 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
344 * -> new_working_state
345 * with inputs
346 * ctx contains working_state
347 * additional[:len] = additional_input
348 * and entropy_input comes from calling ctx->f_entropy
349 * and with output
350 * ctx contains new_working_state
351 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200352int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000353 const unsigned char *additional, size_t len )
354{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200355 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000356 size_t seedlen = 0;
Dvir Markovich1b364992017-06-26 13:43:34 +0300357 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000358
Andres Amaya Garcia6a543362017-01-17 23:04:22 +0000359 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
360 len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200361 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000362
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200363 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000364
365 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200366 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000367 */
368 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
369 ctx->entropy_len ) )
370 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200371 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000372 }
373
374 seedlen += ctx->entropy_len;
375
376 /*
377 * Add additional data
378 */
379 if( additional && len )
380 {
381 memcpy( seed + seedlen, additional, len );
382 seedlen += len;
383 }
384
385 /*
386 * Reduce to 384 bits
387 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300388 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200389 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000390
391 /*
392 * Update state
393 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300394 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200395 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000396 ctx->reseed_counter = 1;
397
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200398exit:
399 mbedtls_platform_zeroize( seed, sizeof( seed ) );
400 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000401}
Paul Bakker9af723c2014-05-01 13:03:14 +0200402
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200403/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
Gilles Peskine912ffe42019-10-04 12:15:55 +0200404 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200405 * implements
406 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
407 * security_strength) -> initial_working_state
408 * with inputs
409 * custom[:len] = nonce || personalization_string
Gilles Peskine912ffe42019-10-04 12:15:55 +0200410 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200411 * and with outputs
412 * ctx = initial_working_state
413 */
Gilles Peskine912ffe42019-10-04 12:15:55 +0200414int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
415 int (*f_entropy)(void *, unsigned char *, size_t),
416 void *p_entropy,
417 const unsigned char *custom,
418 size_t len )
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200419{
420 int ret;
421 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
422
423 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
424
425 mbedtls_aes_init( &ctx->aes_ctx );
426
427 ctx->f_entropy = f_entropy;
428 ctx->p_entropy = p_entropy;
429
Gilles Peskine912ffe42019-10-04 12:15:55 +0200430 if( ctx->entropy_len == 0 )
431 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200432
433 /*
434 * Initialize with an empty key
435 */
436 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
437 {
438 return( ret );
439 }
440
441 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
442 {
443 return( ret );
444 }
445 return( 0 );
446}
447
Gilles Peskine912ffe42019-10-04 12:15:55 +0200448/* Backward compatibility wrapper */
449int mbedtls_ctr_drbg_seed_entropy_len(
450 mbedtls_ctr_drbg_context *ctx,
451 int (*f_entropy)(void *, unsigned char *, size_t), void *p_entropy,
452 const unsigned char *custom, size_t len,
453 size_t entropy_len )
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200454{
Gilles Peskine912ffe42019-10-04 12:15:55 +0200455 mbedtls_ctr_drbg_set_entropy_len( ctx, entropy_len );
456 return( mbedtls_ctr_drbg_seed( ctx, f_entropy, p_entropy, custom, len ) );
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200457}
458
Gilles Peskineed7da592018-08-03 20:16:52 +0200459/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
460 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
461 * implements
462 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
463 * -> working_state_after_reseed
464 * if required, then
465 * CTR_DRBG_Generate(working_state_after_reseed,
466 * requested_number_of_bits, additional_input)
467 * -> status, returned_bits, new_working_state
468 * with inputs
469 * ctx contains working_state
470 * requested_number_of_bits = 8 * output_len
471 * additional[:add_len] = additional_input
472 * and entropy_input comes from calling ctx->f_entropy
473 * and with outputs
474 * status = SUCCESS (this function does the reseed internally)
475 * returned_bits = output[:output_len]
476 * ctx contains new_working_state
477 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200478int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000479 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000480 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000481{
482 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200483 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
484 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000485 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200486 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000487 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000488 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000489
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200490 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
491 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000492
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200493 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
494 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000495
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200496 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000497
498 if( ctx->reseed_counter > ctx->reseed_interval ||
499 ctx->prediction_resistance )
500 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200501 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300502 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000503 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300504 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000505 add_len = 0;
506 }
507
508 if( add_len > 0 )
509 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300510 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200511 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300512 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200513 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000514 }
515
516 while( output_len > 0 )
517 {
518 /*
519 * Increase counter
520 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200521 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000522 if( ++ctx->counter[i - 1] != 0 )
523 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000524
525 /*
526 * Crypt counter block
527 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300528 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200529 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000530
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200531 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200532 output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000533 /*
534 * Copy random block to destination
535 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000536 memcpy( p, tmp, use_len );
537 p += use_len;
538 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000539 }
540
Dvir Markovich1b364992017-06-26 13:43:34 +0300541 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200542 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000543
544 ctx->reseed_counter++;
545
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200546exit:
547 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
548 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
Gilles Peskine86dd9502019-11-28 09:45:32 +0100549 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000550}
551
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200552int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000553{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100554 int ret;
555 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
556
557#if defined(MBEDTLS_THREADING_C)
558 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
559 return( ret );
560#endif
561
562 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
563
564#if defined(MBEDTLS_THREADING_C)
565 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
566 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
567#endif
568
569 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000570}
571
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200572#if defined(MBEDTLS_FS_IO)
573int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000574{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200575 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000576 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200577 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000578
579 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200580 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000581
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200582 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200583 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000584
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200585 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200586 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100587 else
588 ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000589
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100590exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500591 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200592
Paul Bakkerfc754a92011-12-05 13:23:51 +0000593 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200594 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000595}
596
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200597int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000598{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100599 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200600 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000601 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200602 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200603 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000604
605 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200606 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000607
Gilles Peskine82204662018-09-11 18:43:09 +0200608 n = fread( buf, 1, sizeof( buf ), f );
609 if( fread( &c, 1, 1, f ) != 0 )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100610 {
Gilles Peskine82204662018-09-11 18:43:09 +0200611 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
612 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100613 }
Gilles Peskine82204662018-09-11 18:43:09 +0200614 if( n == 0 || ferror( f ) )
615 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100616 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200617 goto exit;
618 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000619 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200620 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200621
Gilles Peskine82204662018-09-11 18:43:09 +0200622 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
623
624exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500625 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200626 if( f != NULL )
627 fclose( f );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100628 if( ret != 0 )
629 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200630 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000631}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200632#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000633
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200634#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000635
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000636static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000637 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
638 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
639 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
640 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
641 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
642 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
643 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
644 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
645 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
646 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
647 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
648 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
649
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000650static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000651 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
652 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
653 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
654 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
655 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
656 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
657 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
658 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
659
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100660static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000661 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
662 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
663
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100664static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000665 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
666 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
667
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100668static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000669 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
670 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
671
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100672static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000673 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
674 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
675
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100676static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200677static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
678 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000679{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100680 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000681 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100682 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000683 return( 0 );
684}
685
Paul Bakker7dc4c442014-02-01 22:50:26 +0100686#define CHK( c ) if( (c) != 0 ) \
687 { \
688 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200689 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100690 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100691 }
692
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000693/*
694 * Checkup routine
695 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200696int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000697{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200698 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000699 unsigned char buf[16];
700
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200701 mbedtls_ctr_drbg_init( &ctx );
702
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000703 /*
704 * Based on a NIST CTR_DRBG test vector (PR = True)
705 */
706 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200707 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000708
709 test_offset = 0;
Gilles Peskine912ffe42019-10-04 12:15:55 +0200710 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
711 CHK( mbedtls_ctr_drbg_seed( &ctx,
712 ctr_drbg_self_test_entropy,
713 (void *) entropy_source_pr,
714 nonce_pers_pr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200715 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
716 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
717 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
718 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000719
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100720 mbedtls_ctr_drbg_free( &ctx );
721
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000722 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200723 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000724
725 /*
726 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
727 */
728 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200729 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000730
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100731 mbedtls_ctr_drbg_init( &ctx );
732
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000733 test_offset = 0;
Gilles Peskine912ffe42019-10-04 12:15:55 +0200734 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
735 CHK( mbedtls_ctr_drbg_seed( &ctx,
736 ctr_drbg_self_test_entropy,
737 (void *) entropy_source_nopr,
738 nonce_pers_nopr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200739 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
740 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
741 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100742 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000743
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100744 mbedtls_ctr_drbg_free( &ctx );
745
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000746 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200747 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000748
749 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200750 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000751
752 return( 0 );
753}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200754#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000755
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200756#endif /* MBEDTLS_CTR_DRBG_C */