blob: ed00765c9addb8c99315ee2a57c0548034ab405b [file] [log] [blame]
Paul Bakker0e04d0e2011-11-27 14:46:59 +00001/*
2 * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Bence Szépkúti4e9f7122020-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úti4e9f7122020-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 * **********
45 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000046 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000047 */
48/*
Paul Sokolovsky8d6d8c82018-02-10 11:11:41 +020049 * The NIST SP 800-90 DRBGs are described in the following publication.
Paul Bakker0e04d0e2011-11-27 14:46:59 +000050 *
51 * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
52 */
53
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020054#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000055#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020056#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020057#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020058#endif
Paul Bakker0e04d0e2011-11-27 14:46:59 +000059
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020060#if defined(MBEDTLS_CTR_DRBG_C)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000061
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000062#include "mbedtls/ctr_drbg.h"
Paul Bakker0e04d0e2011-11-27 14:46:59 +000063
Rich Evans00ab4702015-02-06 13:43:58 +000064#include <string.h>
65
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020066#if defined(MBEDTLS_FS_IO)
Paul Bakkerfc754a92011-12-05 13:23:51 +000067#include <stdio.h>
68#endif
69
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020070#if defined(MBEDTLS_SELF_TEST)
71#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000072#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010073#else
Rich Evans00ab4702015-02-06 13:43:58 +000074#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020075#define mbedtls_printf printf
76#endif /* MBEDTLS_PLATFORM_C */
77#endif /* MBEDTLS_SELF_TEST */
Paul Bakker7dc4c442014-02-01 22:50:26 +010078
Paul Bakkerfff03662014-06-18 16:21:25 +020079/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020080static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakkerfff03662014-06-18 16:21:25 +020081 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
82}
83
Paul Bakker18d32912011-12-10 21:42:49 +000084/*
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020085 * CTR_DRBG context initialization
86 */
87void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
88{
89 memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010090
91#if defined(MBEDTLS_THREADING_C)
92 mbedtls_mutex_init( &ctx->mutex );
93#endif
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020094}
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 );
105 mbedtls_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Paul Bakkerfff03662014-06-18 16:21:25 +0200106}
107
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200108void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000109{
110 ctx->prediction_resistance = resistance;
111}
112
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200113void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000114{
115 ctx->entropy_len = len;
116}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200117
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200118void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000119{
120 ctx->reseed_interval = interval;
121}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200122
123static int block_cipher_df( unsigned char *output,
124 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000125{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200126 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
127 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
128 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
129 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100130 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200131 mbedtls_aes_context aes_ctx;
Dvir Markovich1b364992017-06-26 13:43:34 +0300132 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000133
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200134 int i, j;
135 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000136
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200137 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
138 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100139
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200140 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
141 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000142
143 /*
144 * Construct IV (16 bytes) and S in buffer
145 * IV = Counter (in 32-bits) padded to 16 with zeroes
146 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
147 * data || 0x80
148 * (Total is padded to a multiple of 16-bytes with zeroes)
149 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200150 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000151 *p++ = ( data_len >> 24 ) & 0xff;
152 *p++ = ( data_len >> 16 ) & 0xff;
153 *p++ = ( data_len >> 8 ) & 0xff;
154 *p++ = ( data_len ) & 0xff;
155 p += 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200156 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000157 memcpy( p, data, data_len );
158 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000159
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200160 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000161
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200162 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000163 key[i] = i;
164
Dvir Markovich1b364992017-06-26 13:43:34 +0300165 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
166 {
167 goto exit;
168 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000169
170 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200171 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000172 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200173 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000174 {
175 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200176 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000177 use_len = buf_len;
178
179 while( use_len > 0 )
180 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200181 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000182 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200183 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
184 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
185 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000186
Dvir Markovich1b364992017-06-26 13:43:34 +0300187 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ) ) != 0 )
188 {
189 goto exit;
190 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000191 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200192
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200193 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000194
195 /*
196 * Update IV
197 */
198 buf[3]++;
199 }
200
201 /*
202 * Do final encryption with reduced data
203 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300204 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
205 {
206 goto exit;
207 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200208 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000209 p = output;
210
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200211 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000212 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300213 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) ) != 0 )
214 {
215 goto exit;
216 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200217 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
218 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000219 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300220exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200221 mbedtls_aes_free( &aes_ctx );
Dvir Markovich1b364992017-06-26 13:43:34 +0300222 /*
223 * tidy up the stack
224 */
225 mbedtls_zeroize( buf, sizeof( buf ) );
226 mbedtls_zeroize( tmp, sizeof( tmp ) );
227 mbedtls_zeroize( key, sizeof( key ) );
228 mbedtls_zeroize( chain, sizeof( chain ) );
229 if( 0 != ret )
230 {
231 /*
232 * wipe partial seed from memory
233 */
234 mbedtls_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
235 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200236
Dvir Markovich1b364992017-06-26 13:43:34 +0300237 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000238}
239
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200240static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
241 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000242{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200243 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000244 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000245 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300246 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000247
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200248 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000249
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200250 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000251 {
252 /*
253 * Increase counter
254 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200255 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000256 if( ++ctx->counter[i - 1] != 0 )
257 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000258
259 /*
260 * Crypt counter block
261 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300262 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200263 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000264
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200265 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000266 }
267
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200268 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000269 tmp[i] ^= data[i];
270
271 /*
272 * Update key and counter
273 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300274 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200275 goto exit;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200276 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000277
Gilles Peskined324c592018-09-11 15:34:17 +0200278exit:
279 mbedtls_zeroize( tmp, sizeof( tmp ) );
280 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000281}
282
Gilles Peskine9ce29722018-09-11 16:41:54 +0200283int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
284 const unsigned char *additional,
285 size_t add_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000286{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200287 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Gilles Peskine9ce29722018-09-11 16:41:54 +0200288 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000289
Gilles Peskine9ce29722018-09-11 16:41:54 +0200290 if( add_len == 0 )
291 return( 0 );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100292
Gilles Peskine9ce29722018-09-11 16:41:54 +0200293 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
294 goto exit;
295 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
296 goto exit;
297
298exit:
299 mbedtls_zeroize( add_input, sizeof( add_input ) );
300 return( ret );
301}
302
303/* Deprecated function, kept for backward compatibility. */
304void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
305 const unsigned char *additional,
306 size_t add_len )
307{
308 /* MAX_INPUT would be more logical here, but we have to match
309 * block_cipher_df()'s limits since we can't propagate errors */
310 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
311 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
312 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000313}
314
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200315int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000316 const unsigned char *additional, size_t len )
317{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200318 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000319 size_t seedlen = 0;
Dvir Markovich1b364992017-06-26 13:43:34 +0300320 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000321
Andres Amaya Garcia6a543362017-01-17 23:04:22 +0000322 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
323 len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200324 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000325
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200326 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000327
328 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200329 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000330 */
331 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
332 ctx->entropy_len ) )
333 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200334 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000335 }
336
337 seedlen += ctx->entropy_len;
338
339 /*
340 * Add additional data
341 */
342 if( additional && len )
343 {
344 memcpy( seed + seedlen, additional, len );
345 seedlen += len;
346 }
347
348 /*
349 * Reduce to 384 bits
350 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300351 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200352 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000353
354 /*
355 * Update state
356 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300357 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200358 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000359 ctx->reseed_counter = 1;
360
Gilles Peskined324c592018-09-11 15:34:17 +0200361exit:
362 mbedtls_zeroize( seed, sizeof( seed ) );
363 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000364}
Paul Bakker9af723c2014-05-01 13:03:14 +0200365
Gilles Peskineb729e1b2019-10-04 12:15:55 +0200366int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
367 int (*f_entropy)(void *, unsigned char *, size_t),
368 void *p_entropy,
369 const unsigned char *custom,
370 size_t len )
Gilles Peskine845ac102019-10-02 20:31:54 +0200371{
372 int ret;
373 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
374
375 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
376
377 mbedtls_aes_init( &ctx->aes_ctx );
378
379 ctx->f_entropy = f_entropy;
380 ctx->p_entropy = p_entropy;
381
Gilles Peskineb729e1b2019-10-04 12:15:55 +0200382 if( ctx->entropy_len == 0 )
383 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskine845ac102019-10-02 20:31:54 +0200384 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
385
386 /*
387 * Initialize with an empty key
388 */
389 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
390 {
391 return( ret );
392 }
393
394 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
395 {
396 return( ret );
397 }
398 return( 0 );
399}
400
Gilles Peskineb729e1b2019-10-04 12:15:55 +0200401/* Backward compatibility wrapper */
402int mbedtls_ctr_drbg_seed_entropy_len(
403 mbedtls_ctr_drbg_context *ctx,
404 int (*f_entropy)(void *, unsigned char *, size_t), void *p_entropy,
405 const unsigned char *custom, size_t len,
406 size_t entropy_len )
Gilles Peskine845ac102019-10-02 20:31:54 +0200407{
Gilles Peskineb729e1b2019-10-04 12:15:55 +0200408 mbedtls_ctr_drbg_set_entropy_len( ctx, entropy_len );
409 return( mbedtls_ctr_drbg_seed( ctx, f_entropy, p_entropy, custom, len ) );
Gilles Peskine845ac102019-10-02 20:31:54 +0200410}
411
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200412int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000413 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000414 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000415{
416 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200417 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
418 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000419 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200420 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000421 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000422 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000423
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200424 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
425 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000426
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200427 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
428 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000429
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200430 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000431
432 if( ctx->reseed_counter > ctx->reseed_interval ||
433 ctx->prediction_resistance )
434 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200435 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300436 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000437 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300438 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000439 add_len = 0;
440 }
441
442 if( add_len > 0 )
443 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300444 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200445 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300446 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200447 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000448 }
449
450 while( output_len > 0 )
451 {
452 /*
453 * Increase counter
454 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200455 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000456 if( ++ctx->counter[i - 1] != 0 )
457 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000458
459 /*
460 * Crypt counter block
461 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300462 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200463 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000464
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200465 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200466 output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000467 /*
468 * Copy random block to destination
469 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000470 memcpy( p, tmp, use_len );
471 p += use_len;
472 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000473 }
474
Dvir Markovich1b364992017-06-26 13:43:34 +0300475 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200476 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000477
478 ctx->reseed_counter++;
479
Gilles Peskined324c592018-09-11 15:34:17 +0200480exit:
481 mbedtls_zeroize( add_input, sizeof( add_input ) );
482 mbedtls_zeroize( tmp, sizeof( tmp ) );
Gilles Peskineb2be1fc2019-11-28 09:45:32 +0100483 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000484}
485
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200486int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000487{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100488 int ret;
489 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
490
491#if defined(MBEDTLS_THREADING_C)
492 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
493 return( ret );
494#endif
495
496 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
497
498#if defined(MBEDTLS_THREADING_C)
499 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
500 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
501#endif
502
503 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000504}
505
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200506#if defined(MBEDTLS_FS_IO)
507int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000508{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200509 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000510 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200511 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000512
513 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200514 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000515
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200516 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200517 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000518
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200519 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200520 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100521 else
522 ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000523
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100524exit:
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100525 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200526
Paul Bakkerfc754a92011-12-05 13:23:51 +0000527 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200528 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000529}
530
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200531int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000532{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100533 int ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000534 FILE *f;
535 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200536 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000537
538 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200539 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000540
541 fseek( f, 0, SEEK_END );
542 n = (size_t) ftell( f );
543 fseek( f, 0, SEEK_SET );
544
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200545 if( n > MBEDTLS_CTR_DRBG_MAX_INPUT )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100546 {
547 fclose( f );
548 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
549 }
550
551 if( fread( buf, 1, n, f ) != n )
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100552 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
553 else
Gilles Peskine9ce29722018-09-11 16:41:54 +0200554 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000555
Paul Bakkerfc754a92011-12-05 13:23:51 +0000556 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200557
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100558 mbedtls_zeroize( buf, sizeof( buf ) );
559
560 if( ret != 0 )
561 return( ret );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200562
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200563 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000564}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200565#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000566
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200567#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000568
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000569static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000570 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
571 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
572 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
573 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
574 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
575 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
576 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
577 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
578 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
579 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
580 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
581 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
582
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000583static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000584 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
585 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
586 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
587 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
588 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
589 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
590 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
591 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
592
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100593static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000594 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
595 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
596
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100597static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000598 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
599 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
600
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100601static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000602 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
603 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
604
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100605static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000606 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
607 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
608
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100609static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200610static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
611 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000612{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100613 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000614 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100615 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000616 return( 0 );
617}
618
Paul Bakker7dc4c442014-02-01 22:50:26 +0100619#define CHK( c ) if( (c) != 0 ) \
620 { \
621 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200622 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100623 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100624 }
625
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000626/*
627 * Checkup routine
628 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200629int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000630{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200631 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000632 unsigned char buf[16];
633
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200634 mbedtls_ctr_drbg_init( &ctx );
635
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000636 /*
637 * Based on a NIST CTR_DRBG test vector (PR = True)
638 */
639 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200640 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000641
642 test_offset = 0;
Gilles Peskineb729e1b2019-10-04 12:15:55 +0200643 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
644 CHK( mbedtls_ctr_drbg_seed( &ctx,
645 ctr_drbg_self_test_entropy,
646 (void *) entropy_source_pr,
647 nonce_pers_pr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200648 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
649 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
650 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
651 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000652
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100653 mbedtls_ctr_drbg_free( &ctx );
654
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000655 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200656 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000657
658 /*
659 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
660 */
661 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200662 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000663
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100664 mbedtls_ctr_drbg_init( &ctx );
665
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000666 test_offset = 0;
Gilles Peskineb729e1b2019-10-04 12:15:55 +0200667 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
668 CHK( mbedtls_ctr_drbg_seed( &ctx,
669 ctr_drbg_self_test_entropy,
670 (void *) entropy_source_nopr,
671 nonce_pers_nopr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200672 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
673 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
674 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100675 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000676
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100677 mbedtls_ctr_drbg_free( &ctx );
678
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000679 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200680 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000681
682 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200683 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000684
685 return( 0 );
686}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200687#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000688
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200689#endif /* MBEDTLS_CTR_DRBG_C */