blob: b98df29a9b429826744dfc86e237bd39e02e56a1 [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
85#if defined(MBEDTLS_THREADING_C)
86 mbedtls_mutex_init( &ctx->mutex );
87#endif
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020088}
89
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020090void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
Paul Bakkerfff03662014-06-18 16:21:25 +020091{
92 if( ctx == NULL )
93 return;
94
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010095#if defined(MBEDTLS_THREADING_C)
96 mbedtls_mutex_free( &ctx->mutex );
97#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020098 mbedtls_aes_free( &ctx->aes_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050099 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Paul Bakkerfff03662014-06-18 16:21:25 +0200100}
101
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200102void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000103{
104 ctx->prediction_resistance = resistance;
105}
106
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200107void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000108{
109 ctx->entropy_len = len;
110}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200111
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200112void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000113{
114 ctx->reseed_interval = interval;
115}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200116
117static int block_cipher_df( unsigned char *output,
118 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000119{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200120 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
121 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
122 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
123 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100124 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200125 mbedtls_aes_context aes_ctx;
Dvir Markovich1b364992017-06-26 13:43:34 +0300126 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000127
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200128 int i, j;
129 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000130
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200131 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
132 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100133
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200134 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
135 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000136
137 /*
138 * Construct IV (16 bytes) and S in buffer
139 * IV = Counter (in 32-bits) padded to 16 with zeroes
140 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
141 * data || 0x80
142 * (Total is padded to a multiple of 16-bytes with zeroes)
143 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200144 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000145 *p++ = ( data_len >> 24 ) & 0xff;
146 *p++ = ( data_len >> 16 ) & 0xff;
147 *p++ = ( data_len >> 8 ) & 0xff;
148 *p++ = ( data_len ) & 0xff;
149 p += 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200150 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000151 memcpy( p, data, data_len );
152 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000153
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200154 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000155
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200156 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000157 key[i] = i;
158
Dvir Markovich1b364992017-06-26 13:43:34 +0300159 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
160 {
161 goto exit;
162 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000163
164 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200165 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000166 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200167 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000168 {
169 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200170 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000171 use_len = buf_len;
172
173 while( use_len > 0 )
174 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200175 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000176 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200177 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
178 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
179 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000180
Dvir Markovich1b364992017-06-26 13:43:34 +0300181 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ) ) != 0 )
182 {
183 goto exit;
184 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000185 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200186
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200187 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000188
189 /*
190 * Update IV
191 */
192 buf[3]++;
193 }
194
195 /*
196 * Do final encryption with reduced data
197 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300198 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
199 {
200 goto exit;
201 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200202 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000203 p = output;
204
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200205 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000206 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300207 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) ) != 0 )
208 {
209 goto exit;
210 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200211 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
212 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000213 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300214exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200215 mbedtls_aes_free( &aes_ctx );
Dvir Markovich1b364992017-06-26 13:43:34 +0300216 /*
217 * tidy up the stack
218 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500219 mbedtls_platform_zeroize( buf, sizeof( buf ) );
220 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
221 mbedtls_platform_zeroize( key, sizeof( key ) );
222 mbedtls_platform_zeroize( chain, sizeof( chain ) );
Dvir Markovich1b364992017-06-26 13:43:34 +0300223 if( 0 != ret )
224 {
225 /*
226 * wipe partial seed from memory
227 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500228 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
Dvir Markovich1b364992017-06-26 13:43:34 +0300229 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200230
Dvir Markovich1b364992017-06-26 13:43:34 +0300231 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000232}
233
Gilles Peskineed7da592018-08-03 20:16:52 +0200234/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
235 * ctr_drbg_update_internal(ctx, provided_data)
236 * implements
237 * CTR_DRBG_Update(provided_data, Key, V)
238 * with inputs and outputs
239 * ctx->aes_ctx = Key
240 * ctx->counter = V
241 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200242static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
243 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000244{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200245 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000246 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000247 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300248 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000249
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200250 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000251
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200252 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000253 {
254 /*
255 * Increase counter
256 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200257 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000258 if( ++ctx->counter[i - 1] != 0 )
259 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000260
261 /*
262 * Crypt counter block
263 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300264 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200265 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000266
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200267 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000268 }
269
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200270 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000271 tmp[i] ^= data[i];
272
273 /*
274 * Update key and counter
275 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300276 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200277 goto exit;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200278 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000279
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200280exit:
281 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
282 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000283}
284
Gilles Peskineed7da592018-08-03 20:16:52 +0200285/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
286 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
287 * implements
288 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
289 * security_strength) -> initial_working_state
290 * with inputs
291 * ctx->counter = all-bits-0
292 * ctx->aes_ctx = context from all-bits-0 key
293 * additional[:add_len] = entropy_input || nonce || personalization_string
294 * and with outputs
295 * ctx = initial_working_state
296 */
Gilles Peskined9199932018-09-11 16:41:54 +0200297int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
298 const unsigned char *additional,
299 size_t add_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000300{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200301 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Gilles Peskined9199932018-09-11 16:41:54 +0200302 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000303
Gilles Peskined9199932018-09-11 16:41:54 +0200304 if( add_len == 0 )
305 return( 0 );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100306
Gilles Peskined9199932018-09-11 16:41:54 +0200307 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
308 goto exit;
309 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
310 goto exit;
311
312exit:
313 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
314 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000315}
316
Gilles Peskined9199932018-09-11 16:41:54 +0200317#if !defined(MBEDTLS_DEPRECATED_REMOVED)
318void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
319 const unsigned char *additional,
320 size_t add_len )
321{
322 /* MAX_INPUT would be more logical here, but we have to match
323 * block_cipher_df()'s limits since we can't propagate errors */
324 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
325 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
326 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
327}
328#endif /* MBEDTLS_DEPRECATED_REMOVED */
329
Gilles Peskineed7da592018-08-03 20:16:52 +0200330/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
331 * mbedtls_ctr_drbg_reseed(ctx, additional, len)
332 * implements
333 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
334 * -> new_working_state
335 * with inputs
336 * ctx contains working_state
337 * additional[:len] = additional_input
338 * and entropy_input comes from calling ctx->f_entropy
339 * and with output
340 * ctx contains new_working_state
341 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200342int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000343 const unsigned char *additional, size_t len )
344{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200345 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000346 size_t seedlen = 0;
Dvir Markovich1b364992017-06-26 13:43:34 +0300347 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000348
Andres Amaya Garcia6a543362017-01-17 23:04:22 +0000349 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
350 len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200351 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000352
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200353 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000354
355 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200356 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000357 */
358 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
359 ctx->entropy_len ) )
360 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200361 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000362 }
363
364 seedlen += ctx->entropy_len;
365
366 /*
367 * Add additional data
368 */
369 if( additional && len )
370 {
371 memcpy( seed + seedlen, additional, len );
372 seedlen += len;
373 }
374
375 /*
376 * Reduce to 384 bits
377 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300378 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200379 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000380
381 /*
382 * Update state
383 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300384 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200385 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000386 ctx->reseed_counter = 1;
387
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200388exit:
389 mbedtls_platform_zeroize( seed, sizeof( seed ) );
390 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000391}
Paul Bakker9af723c2014-05-01 13:03:14 +0200392
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200393/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
Gilles Peskine912ffe42019-10-04 12:15:55 +0200394 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200395 * implements
396 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
397 * security_strength) -> initial_working_state
398 * with inputs
399 * custom[:len] = nonce || personalization_string
Gilles Peskine912ffe42019-10-04 12:15:55 +0200400 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200401 * and with outputs
402 * ctx = initial_working_state
403 */
Gilles Peskine912ffe42019-10-04 12:15:55 +0200404int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
405 int (*f_entropy)(void *, unsigned char *, size_t),
406 void *p_entropy,
407 const unsigned char *custom,
408 size_t len )
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200409{
410 int ret;
411 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
412
413 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
414
415 mbedtls_aes_init( &ctx->aes_ctx );
416
417 ctx->f_entropy = f_entropy;
418 ctx->p_entropy = p_entropy;
419
Gilles Peskine912ffe42019-10-04 12:15:55 +0200420 if( ctx->entropy_len == 0 )
421 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200422 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
423
424 /*
425 * Initialize with an empty key
426 */
427 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
428 {
429 return( ret );
430 }
431
432 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
433 {
434 return( ret );
435 }
436 return( 0 );
437}
438
Gilles Peskine912ffe42019-10-04 12:15:55 +0200439/* Backward compatibility wrapper */
440int mbedtls_ctr_drbg_seed_entropy_len(
441 mbedtls_ctr_drbg_context *ctx,
442 int (*f_entropy)(void *, unsigned char *, size_t), void *p_entropy,
443 const unsigned char *custom, size_t len,
444 size_t entropy_len )
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200445{
Gilles Peskine912ffe42019-10-04 12:15:55 +0200446 mbedtls_ctr_drbg_set_entropy_len( ctx, entropy_len );
447 return( mbedtls_ctr_drbg_seed( ctx, f_entropy, p_entropy, custom, len ) );
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200448}
449
Gilles Peskineed7da592018-08-03 20:16:52 +0200450/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
451 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
452 * implements
453 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
454 * -> working_state_after_reseed
455 * if required, then
456 * CTR_DRBG_Generate(working_state_after_reseed,
457 * requested_number_of_bits, additional_input)
458 * -> status, returned_bits, new_working_state
459 * with inputs
460 * ctx contains working_state
461 * requested_number_of_bits = 8 * output_len
462 * additional[:add_len] = additional_input
463 * and entropy_input comes from calling ctx->f_entropy
464 * and with outputs
465 * status = SUCCESS (this function does the reseed internally)
466 * returned_bits = output[:output_len]
467 * ctx contains new_working_state
468 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200469int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000470 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000471 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000472{
473 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200474 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
475 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000476 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200477 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000478 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000479 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
482 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000483
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200484 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
485 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000486
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200487 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000488
489 if( ctx->reseed_counter > ctx->reseed_interval ||
490 ctx->prediction_resistance )
491 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200492 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300493 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000494 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300495 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000496 add_len = 0;
497 }
498
499 if( add_len > 0 )
500 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300501 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200502 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300503 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200504 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000505 }
506
507 while( output_len > 0 )
508 {
509 /*
510 * Increase counter
511 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200512 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000513 if( ++ctx->counter[i - 1] != 0 )
514 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000515
516 /*
517 * Crypt counter block
518 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300519 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200520 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000521
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200522 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200523 output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000524 /*
525 * Copy random block to destination
526 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000527 memcpy( p, tmp, use_len );
528 p += use_len;
529 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000530 }
531
Dvir Markovich1b364992017-06-26 13:43:34 +0300532 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200533 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000534
535 ctx->reseed_counter++;
536
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200537exit:
538 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
539 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
Gilles Peskine86dd9502019-11-28 09:45:32 +0100540 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000541}
542
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200543int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000544{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100545 int ret;
546 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
547
548#if defined(MBEDTLS_THREADING_C)
549 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
550 return( ret );
551#endif
552
553 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
554
555#if defined(MBEDTLS_THREADING_C)
556 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
557 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
558#endif
559
560 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000561}
562
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200563#if defined(MBEDTLS_FS_IO)
564int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000565{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200566 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000567 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200568 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000569
570 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200571 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000572
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200573 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200574 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000575
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200576 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200577 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100578 else
579 ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000580
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100581exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500582 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200583
Paul Bakkerfc754a92011-12-05 13:23:51 +0000584 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200585 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000586}
587
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200588int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000589{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100590 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200591 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000592 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200593 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200594 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000595
596 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200597 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000598
Gilles Peskine82204662018-09-11 18:43:09 +0200599 n = fread( buf, 1, sizeof( buf ), f );
600 if( fread( &c, 1, 1, f ) != 0 )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100601 {
Gilles Peskine82204662018-09-11 18:43:09 +0200602 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
603 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100604 }
Gilles Peskine82204662018-09-11 18:43:09 +0200605 if( n == 0 || ferror( f ) )
606 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100607 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200608 goto exit;
609 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000610 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200611 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200612
Gilles Peskine82204662018-09-11 18:43:09 +0200613 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
614
615exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500616 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200617 if( f != NULL )
618 fclose( f );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100619 if( ret != 0 )
620 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200621 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000622}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200623#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000624
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200625#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000626
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000627static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000628 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
629 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
630 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
631 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
632 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
633 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
634 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
635 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
636 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
637 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
638 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
639 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
640
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000641static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000642 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
643 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
644 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
645 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
646 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
647 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
648 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
649 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
650
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100651static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000652 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
653 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
654
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100655static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000656 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
657 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
658
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100659static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000660 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
661 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
662
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100663static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000664 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
665 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
666
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100667static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200668static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
669 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000670{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100671 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000672 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100673 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000674 return( 0 );
675}
676
Paul Bakker7dc4c442014-02-01 22:50:26 +0100677#define CHK( c ) if( (c) != 0 ) \
678 { \
679 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200680 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100681 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100682 }
683
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000684/*
685 * Checkup routine
686 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200687int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000688{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200689 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000690 unsigned char buf[16];
691
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200692 mbedtls_ctr_drbg_init( &ctx );
693
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000694 /*
695 * Based on a NIST CTR_DRBG test vector (PR = True)
696 */
697 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200698 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000699
700 test_offset = 0;
Gilles Peskine912ffe42019-10-04 12:15:55 +0200701 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
702 CHK( mbedtls_ctr_drbg_seed( &ctx,
703 ctr_drbg_self_test_entropy,
704 (void *) entropy_source_pr,
705 nonce_pers_pr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200706 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
707 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
708 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
709 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000710
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100711 mbedtls_ctr_drbg_free( &ctx );
712
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000713 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200714 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000715
716 /*
717 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
718 */
719 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200720 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000721
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100722 mbedtls_ctr_drbg_init( &ctx );
723
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000724 test_offset = 0;
Gilles Peskine912ffe42019-10-04 12:15:55 +0200725 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
726 CHK( mbedtls_ctr_drbg_seed( &ctx,
727 ctr_drbg_self_test_entropy,
728 (void *) entropy_source_nopr,
729 nonce_pers_nopr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200730 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
731 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
732 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100733 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000734
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100735 mbedtls_ctr_drbg_free( &ctx );
736
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000737 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200738 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000739
740 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200741 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000742
743 return( 0 );
744}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200745#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000746
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200747#endif /* MBEDTLS_CTR_DRBG_C */