blob: 184e09fc1041b5864de6f99fd400cf8b3b879123 [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úti44bfbe32020-08-19 16:54:51 +02004 * Copyright The Mbed TLS Contributors
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 * **********
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"
Paul Bakker0e04d0e2011-11-27 14:46:59 +000061
Rich Evans00ab4702015-02-06 13:43:58 +000062#include <string.h>
63
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020064#if defined(MBEDTLS_FS_IO)
Paul Bakkerfc754a92011-12-05 13:23:51 +000065#include <stdio.h>
66#endif
67
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020068#if defined(MBEDTLS_SELF_TEST)
69#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000070#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010071#else
Rich Evans00ab4702015-02-06 13:43:58 +000072#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020073#define mbedtls_printf printf
74#endif /* MBEDTLS_PLATFORM_C */
75#endif /* MBEDTLS_SELF_TEST */
Paul Bakker7dc4c442014-02-01 22:50:26 +010076
Paul Bakkerfff03662014-06-18 16:21:25 +020077/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020078static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakkerfff03662014-06-18 16:21:25 +020079 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
80}
81
Paul Bakker18d32912011-12-10 21:42:49 +000082/*
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020083 * CTR_DRBG context initialization
84 */
85void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
86{
87 memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010088
89#if defined(MBEDTLS_THREADING_C)
90 mbedtls_mutex_init( &ctx->mutex );
91#endif
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020092}
93
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020094void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
Paul Bakkerfff03662014-06-18 16:21:25 +020095{
96 if( ctx == NULL )
97 return;
98
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010099#if defined(MBEDTLS_THREADING_C)
100 mbedtls_mutex_free( &ctx->mutex );
101#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200102 mbedtls_aes_free( &ctx->aes_ctx );
103 mbedtls_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Paul Bakkerfff03662014-06-18 16:21:25 +0200104}
105
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200106void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000107{
108 ctx->prediction_resistance = resistance;
109}
110
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200111void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000112{
113 ctx->entropy_len = len;
114}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200115
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200116void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000117{
118 ctx->reseed_interval = interval;
119}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200120
121static int block_cipher_df( unsigned char *output,
122 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000123{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200124 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
125 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
126 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
127 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100128 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200129 mbedtls_aes_context aes_ctx;
Dvir Markovich1b364992017-06-26 13:43:34 +0300130 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000131
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200132 int i, j;
133 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000134
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200135 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
136 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100137
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200138 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
139 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000140
141 /*
142 * Construct IV (16 bytes) and S in buffer
143 * IV = Counter (in 32-bits) padded to 16 with zeroes
144 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
145 * data || 0x80
146 * (Total is padded to a multiple of 16-bytes with zeroes)
147 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200148 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000149 *p++ = ( data_len >> 24 ) & 0xff;
150 *p++ = ( data_len >> 16 ) & 0xff;
151 *p++ = ( data_len >> 8 ) & 0xff;
152 *p++ = ( data_len ) & 0xff;
153 p += 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200154 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000155 memcpy( p, data, data_len );
156 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000157
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200158 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000159
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200160 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000161 key[i] = i;
162
Dvir Markovich1b364992017-06-26 13:43:34 +0300163 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
164 {
165 goto exit;
166 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000167
168 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200169 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000170 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200171 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000172 {
173 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200174 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000175 use_len = buf_len;
176
177 while( use_len > 0 )
178 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200179 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000180 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200181 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
182 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
183 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000184
Dvir Markovich1b364992017-06-26 13:43:34 +0300185 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ) ) != 0 )
186 {
187 goto exit;
188 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000189 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200190
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200191 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000192
193 /*
194 * Update IV
195 */
196 buf[3]++;
197 }
198
199 /*
200 * Do final encryption with reduced data
201 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300202 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
203 {
204 goto exit;
205 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200206 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000207 p = output;
208
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200209 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000210 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300211 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) ) != 0 )
212 {
213 goto exit;
214 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200215 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
216 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000217 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300218exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200219 mbedtls_aes_free( &aes_ctx );
Dvir Markovich1b364992017-06-26 13:43:34 +0300220 /*
221 * tidy up the stack
222 */
223 mbedtls_zeroize( buf, sizeof( buf ) );
224 mbedtls_zeroize( tmp, sizeof( tmp ) );
225 mbedtls_zeroize( key, sizeof( key ) );
226 mbedtls_zeroize( chain, sizeof( chain ) );
227 if( 0 != ret )
228 {
229 /*
230 * wipe partial seed from memory
231 */
232 mbedtls_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
233 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200234
Dvir Markovich1b364992017-06-26 13:43:34 +0300235 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000236}
237
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200238static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
239 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000240{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200241 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000242 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000243 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300244 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000245
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200246 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000247
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200248 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000249 {
250 /*
251 * Increase counter
252 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200253 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000254 if( ++ctx->counter[i - 1] != 0 )
255 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000256
257 /*
258 * Crypt counter block
259 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300260 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200261 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000262
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200263 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000264 }
265
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200266 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000267 tmp[i] ^= data[i];
268
269 /*
270 * Update key and counter
271 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300272 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200273 goto exit;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200274 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000275
Gilles Peskined324c592018-09-11 15:34:17 +0200276exit:
277 mbedtls_zeroize( tmp, sizeof( tmp ) );
278 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000279}
280
Gilles Peskine9ce29722018-09-11 16:41:54 +0200281int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
282 const unsigned char *additional,
283 size_t add_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000284{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200285 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Gilles Peskine9ce29722018-09-11 16:41:54 +0200286 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000287
Gilles Peskine9ce29722018-09-11 16:41:54 +0200288 if( add_len == 0 )
289 return( 0 );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100290
Gilles Peskine9ce29722018-09-11 16:41:54 +0200291 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
292 goto exit;
293 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
294 goto exit;
295
296exit:
297 mbedtls_zeroize( add_input, sizeof( add_input ) );
298 return( ret );
299}
300
301/* Deprecated function, kept for backward compatibility. */
302void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
303 const unsigned char *additional,
304 size_t add_len )
305{
306 /* MAX_INPUT would be more logical here, but we have to match
307 * block_cipher_df()'s limits since we can't propagate errors */
308 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
309 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
310 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000311}
312
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200313int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000314 const unsigned char *additional, size_t len )
315{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200316 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000317 size_t seedlen = 0;
Dvir Markovich1b364992017-06-26 13:43:34 +0300318 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000319
Andres Amaya Garcia6a543362017-01-17 23:04:22 +0000320 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
321 len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200322 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000323
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200324 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000325
326 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200327 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000328 */
329 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
330 ctx->entropy_len ) )
331 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200332 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000333 }
334
335 seedlen += ctx->entropy_len;
336
337 /*
338 * Add additional data
339 */
340 if( additional && len )
341 {
342 memcpy( seed + seedlen, additional, len );
343 seedlen += len;
344 }
345
346 /*
347 * Reduce to 384 bits
348 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300349 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200350 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000351
352 /*
353 * Update state
354 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300355 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200356 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000357 ctx->reseed_counter = 1;
358
Gilles Peskined324c592018-09-11 15:34:17 +0200359exit:
360 mbedtls_zeroize( seed, sizeof( seed ) );
361 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000362}
Paul Bakker9af723c2014-05-01 13:03:14 +0200363
Gilles Peskineb729e1b2019-10-04 12:15:55 +0200364int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
365 int (*f_entropy)(void *, unsigned char *, size_t),
366 void *p_entropy,
367 const unsigned char *custom,
368 size_t len )
Gilles Peskine845ac102019-10-02 20:31:54 +0200369{
370 int ret;
371 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
372
373 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
374
375 mbedtls_aes_init( &ctx->aes_ctx );
376
377 ctx->f_entropy = f_entropy;
378 ctx->p_entropy = p_entropy;
379
Gilles Peskineb729e1b2019-10-04 12:15:55 +0200380 if( ctx->entropy_len == 0 )
381 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskine845ac102019-10-02 20:31:54 +0200382 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
383
384 /*
385 * Initialize with an empty key
386 */
387 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
388 {
389 return( ret );
390 }
391
392 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
393 {
394 return( ret );
395 }
396 return( 0 );
397}
398
Gilles Peskineb729e1b2019-10-04 12:15:55 +0200399/* Backward compatibility wrapper */
400int mbedtls_ctr_drbg_seed_entropy_len(
401 mbedtls_ctr_drbg_context *ctx,
402 int (*f_entropy)(void *, unsigned char *, size_t), void *p_entropy,
403 const unsigned char *custom, size_t len,
404 size_t entropy_len )
Gilles Peskine845ac102019-10-02 20:31:54 +0200405{
Gilles Peskineb729e1b2019-10-04 12:15:55 +0200406 mbedtls_ctr_drbg_set_entropy_len( ctx, entropy_len );
407 return( mbedtls_ctr_drbg_seed( ctx, f_entropy, p_entropy, custom, len ) );
Gilles Peskine845ac102019-10-02 20:31:54 +0200408}
409
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200410int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000411 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000412 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000413{
414 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200415 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
416 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000417 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200418 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000419 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000420 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000421
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200422 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
423 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000424
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200425 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
426 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000427
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200428 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000429
430 if( ctx->reseed_counter > ctx->reseed_interval ||
431 ctx->prediction_resistance )
432 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200433 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300434 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000435 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300436 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000437 add_len = 0;
438 }
439
440 if( add_len > 0 )
441 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300442 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200443 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300444 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200445 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000446 }
447
448 while( output_len > 0 )
449 {
450 /*
451 * Increase counter
452 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200453 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000454 if( ++ctx->counter[i - 1] != 0 )
455 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000456
457 /*
458 * Crypt counter block
459 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300460 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200461 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000462
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200463 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200464 output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000465 /*
466 * Copy random block to destination
467 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000468 memcpy( p, tmp, use_len );
469 p += use_len;
470 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000471 }
472
Dvir Markovich1b364992017-06-26 13:43:34 +0300473 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200474 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000475
476 ctx->reseed_counter++;
477
Gilles Peskined324c592018-09-11 15:34:17 +0200478exit:
479 mbedtls_zeroize( add_input, sizeof( add_input ) );
480 mbedtls_zeroize( tmp, sizeof( tmp ) );
Gilles Peskineb2be1fc2019-11-28 09:45:32 +0100481 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000482}
483
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200484int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000485{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100486 int ret;
487 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
488
489#if defined(MBEDTLS_THREADING_C)
490 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
491 return( ret );
492#endif
493
494 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
495
496#if defined(MBEDTLS_THREADING_C)
497 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
498 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
499#endif
500
501 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000502}
503
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200504#if defined(MBEDTLS_FS_IO)
505int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000506{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200507 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000508 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200509 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000510
511 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200512 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000513
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200514 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200515 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000516
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200517 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200518 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100519 else
520 ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000521
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100522exit:
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100523 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200524
Paul Bakkerfc754a92011-12-05 13:23:51 +0000525 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200526 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000527}
528
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200529int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000530{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100531 int ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000532 FILE *f;
533 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200534 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000535
536 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200537 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000538
539 fseek( f, 0, SEEK_END );
540 n = (size_t) ftell( f );
541 fseek( f, 0, SEEK_SET );
542
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200543 if( n > MBEDTLS_CTR_DRBG_MAX_INPUT )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100544 {
545 fclose( f );
546 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
547 }
548
549 if( fread( buf, 1, n, f ) != n )
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100550 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
551 else
Gilles Peskine9ce29722018-09-11 16:41:54 +0200552 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000553
Paul Bakkerfc754a92011-12-05 13:23:51 +0000554 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200555
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100556 mbedtls_zeroize( buf, sizeof( buf ) );
557
558 if( ret != 0 )
559 return( ret );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200560
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200561 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000562}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200563#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000564
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200565#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000566
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000567static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000568 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
569 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
570 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
571 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
572 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
573 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
574 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
575 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
576 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
577 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
578 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
579 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
580
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000581static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000582 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
583 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
584 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
585 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
586 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
587 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
588 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
589 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
590
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100591static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000592 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
593 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
594
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100595static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000596 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
597 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
598
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100599static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000600 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
601 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
602
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100603static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000604 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
605 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
606
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100607static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200608static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
609 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000610{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100611 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000612 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100613 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000614 return( 0 );
615}
616
Paul Bakker7dc4c442014-02-01 22:50:26 +0100617#define CHK( c ) if( (c) != 0 ) \
618 { \
619 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200620 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100621 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100622 }
623
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000624/*
625 * Checkup routine
626 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200627int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000628{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200629 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000630 unsigned char buf[16];
631
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200632 mbedtls_ctr_drbg_init( &ctx );
633
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000634 /*
635 * Based on a NIST CTR_DRBG test vector (PR = True)
636 */
637 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200638 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000639
640 test_offset = 0;
Gilles Peskineb729e1b2019-10-04 12:15:55 +0200641 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
642 CHK( mbedtls_ctr_drbg_seed( &ctx,
643 ctr_drbg_self_test_entropy,
644 (void *) entropy_source_pr,
645 nonce_pers_pr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200646 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
647 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
648 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
649 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000650
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100651 mbedtls_ctr_drbg_free( &ctx );
652
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000653 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200654 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000655
656 /*
657 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
658 */
659 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200660 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000661
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100662 mbedtls_ctr_drbg_init( &ctx );
663
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000664 test_offset = 0;
Gilles Peskineb729e1b2019-10-04 12:15:55 +0200665 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
666 CHK( mbedtls_ctr_drbg_seed( &ctx,
667 ctr_drbg_self_test_entropy,
668 (void *) entropy_source_nopr,
669 nonce_pers_nopr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200670 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
671 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
672 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100673 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000674
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100675 mbedtls_ctr_drbg_free( &ctx );
676
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000677 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200678 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000679
680 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200681 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000682
683 return( 0 );
684}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200685#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000686
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200687#endif /* MBEDTLS_CTR_DRBG_C */