blob: 90264e844a4daed40c9c0ec649a431bc5d92d25c [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;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020086}
87
Gavin Acquroff77cb30c2020-03-01 17:06:11 -080088/*
89 * This function resets CTR_DRBG context to the state immediately
90 * after initial call of mbedtls_ctr_drbg_init().
91 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020092void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
Paul Bakkerfff03662014-06-18 16:21:25 +020093{
94 if( ctx == NULL )
95 return;
96
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010097#if defined(MBEDTLS_THREADING_C)
Gilles Peskine2ecc0b82021-02-09 18:44:02 +010098 /* The mutex is initialized iff f_entropy is set. */
Gilles Peskine89816bc2021-01-30 13:05:32 +010099 if( ctx->f_entropy != NULL )
100 mbedtls_mutex_free( &ctx->mutex );
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100101#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200102 mbedtls_aes_free( &ctx->aes_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500103 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Gavin Acquroff77cb30c2020-03-01 17:06:11 -0800104 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
Paul Bakkerfff03662014-06-18 16:21:25 +0200105}
106
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200107void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000108{
109 ctx->prediction_resistance = resistance;
110}
111
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200112void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000113{
114 ctx->entropy_len = len;
115}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200116
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200117void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000118{
119 ctx->reseed_interval = interval;
120}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200121
122static int block_cipher_df( unsigned char *output,
123 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000124{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200125 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
126 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
127 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
128 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100129 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200130 mbedtls_aes_context aes_ctx;
Dvir Markovich1b364992017-06-26 13:43:34 +0300131 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000132
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200133 int i, j;
134 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000135
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200136 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
137 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100138
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200139 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
140 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000141
142 /*
143 * Construct IV (16 bytes) and S in buffer
144 * IV = Counter (in 32-bits) padded to 16 with zeroes
145 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
146 * data || 0x80
147 * (Total is padded to a multiple of 16-bytes with zeroes)
148 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200149 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000150 *p++ = ( data_len >> 24 ) & 0xff;
151 *p++ = ( data_len >> 16 ) & 0xff;
152 *p++ = ( data_len >> 8 ) & 0xff;
153 *p++ = ( data_len ) & 0xff;
154 p += 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200155 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000156 memcpy( p, data, data_len );
157 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000158
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200159 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000160
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200161 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000162 key[i] = i;
163
Dvir Markovich1b364992017-06-26 13:43:34 +0300164 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
165 {
166 goto exit;
167 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000168
169 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200170 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000171 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200172 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000173 {
174 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200175 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000176 use_len = buf_len;
177
178 while( use_len > 0 )
179 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200180 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000181 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200182 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
183 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
184 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000185
Dvir Markovich1b364992017-06-26 13:43:34 +0300186 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ) ) != 0 )
187 {
188 goto exit;
189 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000190 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200191
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200192 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000193
194 /*
195 * Update IV
196 */
197 buf[3]++;
198 }
199
200 /*
201 * Do final encryption with reduced data
202 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300203 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
204 {
205 goto exit;
206 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200207 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000208 p = output;
209
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200210 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000211 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300212 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) ) != 0 )
213 {
214 goto exit;
215 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200216 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
217 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000218 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300219exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200220 mbedtls_aes_free( &aes_ctx );
Dvir Markovich1b364992017-06-26 13:43:34 +0300221 /*
222 * tidy up the stack
223 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500224 mbedtls_platform_zeroize( buf, sizeof( buf ) );
225 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
226 mbedtls_platform_zeroize( key, sizeof( key ) );
227 mbedtls_platform_zeroize( chain, sizeof( chain ) );
Dvir Markovich1b364992017-06-26 13:43:34 +0300228 if( 0 != ret )
229 {
230 /*
231 * wipe partial seed from memory
232 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500233 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
Dvir Markovich1b364992017-06-26 13:43:34 +0300234 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200235
Dvir Markovich1b364992017-06-26 13:43:34 +0300236 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000237}
238
Gilles Peskineed7da592018-08-03 20:16:52 +0200239/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
240 * ctr_drbg_update_internal(ctx, provided_data)
241 * implements
242 * CTR_DRBG_Update(provided_data, Key, V)
243 * with inputs and outputs
244 * ctx->aes_ctx = Key
245 * ctx->counter = V
246 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200247static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
248 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000249{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200250 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000251 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000252 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300253 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000254
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200255 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000256
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200257 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000258 {
259 /*
260 * Increase counter
261 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200262 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000263 if( ++ctx->counter[i - 1] != 0 )
264 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000265
266 /*
267 * Crypt counter block
268 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300269 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200270 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000271
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200272 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000273 }
274
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200275 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000276 tmp[i] ^= data[i];
277
278 /*
279 * Update key and counter
280 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300281 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200282 goto exit;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200283 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000284
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200285exit:
286 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
287 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000288}
289
Gilles Peskineed7da592018-08-03 20:16:52 +0200290/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
291 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
292 * implements
293 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
294 * security_strength) -> initial_working_state
295 * with inputs
296 * ctx->counter = all-bits-0
297 * ctx->aes_ctx = context from all-bits-0 key
298 * additional[:add_len] = entropy_input || nonce || personalization_string
299 * and with outputs
300 * ctx = initial_working_state
301 */
Gilles Peskined9199932018-09-11 16:41:54 +0200302int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
303 const unsigned char *additional,
304 size_t add_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000305{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200306 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Gilles Peskined9199932018-09-11 16:41:54 +0200307 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000308
Gilles Peskined9199932018-09-11 16:41:54 +0200309 if( add_len == 0 )
310 return( 0 );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100311
Gilles Peskined9199932018-09-11 16:41:54 +0200312 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
313 goto exit;
314 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
315 goto exit;
316
317exit:
318 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
319 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000320}
321
Gilles Peskined9199932018-09-11 16:41:54 +0200322#if !defined(MBEDTLS_DEPRECATED_REMOVED)
323void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
324 const unsigned char *additional,
325 size_t add_len )
326{
327 /* MAX_INPUT would be more logical here, but we have to match
328 * block_cipher_df()'s limits since we can't propagate errors */
329 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
330 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
331 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
332}
333#endif /* MBEDTLS_DEPRECATED_REMOVED */
334
Gilles Peskineed7da592018-08-03 20:16:52 +0200335/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
336 * mbedtls_ctr_drbg_reseed(ctx, additional, len)
337 * implements
338 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
339 * -> new_working_state
340 * with inputs
341 * ctx contains working_state
342 * additional[:len] = additional_input
343 * and entropy_input comes from calling ctx->f_entropy
344 * and with output
345 * ctx contains new_working_state
346 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200347int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000348 const unsigned char *additional, size_t len )
349{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200350 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000351 size_t seedlen = 0;
Dvir Markovich1b364992017-06-26 13:43:34 +0300352 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000353
Andres Amaya Garcia6a543362017-01-17 23:04:22 +0000354 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
355 len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200356 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000357
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200358 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000359
360 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200361 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000362 */
363 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
364 ctx->entropy_len ) )
365 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200366 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000367 }
368
369 seedlen += ctx->entropy_len;
370
371 /*
372 * Add additional data
373 */
374 if( additional && len )
375 {
376 memcpy( seed + seedlen, additional, len );
377 seedlen += len;
378 }
379
380 /*
381 * Reduce to 384 bits
382 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300383 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200384 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000385
386 /*
387 * Update state
388 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300389 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200390 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000391 ctx->reseed_counter = 1;
392
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200393exit:
394 mbedtls_platform_zeroize( seed, sizeof( seed ) );
395 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000396}
Paul Bakker9af723c2014-05-01 13:03:14 +0200397
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200398/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
Gilles Peskine912ffe42019-10-04 12:15:55 +0200399 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200400 * implements
401 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
402 * security_strength) -> initial_working_state
403 * with inputs
404 * custom[:len] = nonce || personalization_string
Gilles Peskine912ffe42019-10-04 12:15:55 +0200405 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200406 * and with outputs
407 * ctx = initial_working_state
408 */
Gilles Peskine912ffe42019-10-04 12:15:55 +0200409int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
410 int (*f_entropy)(void *, unsigned char *, size_t),
411 void *p_entropy,
412 const unsigned char *custom,
413 size_t len )
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200414{
415 int ret;
416 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
417
418 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
419
Gilles Peskine2ecc0b82021-02-09 18:44:02 +0100420 /* The mutex is initialized iff f_entropy is set. */
Gilles Peskine89816bc2021-01-30 13:05:32 +0100421#if defined(MBEDTLS_THREADING_C)
422 mbedtls_mutex_init( &ctx->mutex );
423#endif
424
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200425 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 */