blob: e275f1a7287d0da3c1bfaa2adec218f85ae072ac [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
Gavin Acquroffceb99902020-03-01 17:06:11 -080089 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020090}
91
Gavin Acquroffceb99902020-03-01 17:06:11 -080092/*
93 * This function resets CTR_DRBG context to the state immediately
94 * after initial call of mbedtls_ctr_drbg_init().
95 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020096void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
Paul Bakkerfff03662014-06-18 16:21:25 +020097{
98 if( ctx == NULL )
99 return;
100
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100101#if defined(MBEDTLS_THREADING_C)
Gilles Peskine6e2cf252021-02-09 18:44:02 +0100102 /* The mutex is initialized iff f_entropy is set. */
Gilles Peskine085b69f2021-01-30 13:05:32 +0100103 if( ctx->f_entropy != NULL )
104 mbedtls_mutex_free( &ctx->mutex );
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100105#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200106 mbedtls_aes_free( &ctx->aes_ctx );
107 mbedtls_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Gavin Acquroffceb99902020-03-01 17:06:11 -0800108 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
Paul Bakkerfff03662014-06-18 16:21:25 +0200109}
110
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200111void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000112{
113 ctx->prediction_resistance = resistance;
114}
115
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200116void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000117{
118 ctx->entropy_len = len;
119}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200120
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200121void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000122{
123 ctx->reseed_interval = interval;
124}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200125
126static int block_cipher_df( unsigned char *output,
127 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000128{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200129 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
130 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
131 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
132 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100133 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200134 mbedtls_aes_context aes_ctx;
Dvir Markovich1b364992017-06-26 13:43:34 +0300135 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000136
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200137 int i, j;
138 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000139
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200140 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
141 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100142
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200143 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
144 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000145
146 /*
147 * Construct IV (16 bytes) and S in buffer
148 * IV = Counter (in 32-bits) padded to 16 with zeroes
149 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
150 * data || 0x80
151 * (Total is padded to a multiple of 16-bytes with zeroes)
152 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200153 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000154 *p++ = ( data_len >> 24 ) & 0xff;
155 *p++ = ( data_len >> 16 ) & 0xff;
156 *p++ = ( data_len >> 8 ) & 0xff;
157 *p++ = ( data_len ) & 0xff;
158 p += 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200159 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000160 memcpy( p, data, data_len );
161 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000162
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200163 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000164
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200165 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000166 key[i] = i;
167
Dvir Markovich1b364992017-06-26 13:43:34 +0300168 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
169 {
170 goto exit;
171 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000172
173 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200174 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000175 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200176 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000177 {
178 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200179 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000180 use_len = buf_len;
181
182 while( use_len > 0 )
183 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200184 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000185 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200186 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
187 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
188 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000189
Dvir Markovich1b364992017-06-26 13:43:34 +0300190 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ) ) != 0 )
191 {
192 goto exit;
193 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000194 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200195
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200196 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000197
198 /*
199 * Update IV
200 */
201 buf[3]++;
202 }
203
204 /*
205 * Do final encryption with reduced data
206 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300207 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
208 {
209 goto exit;
210 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200211 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000212 p = output;
213
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200214 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000215 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300216 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) ) != 0 )
217 {
218 goto exit;
219 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200220 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
221 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000222 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300223exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200224 mbedtls_aes_free( &aes_ctx );
Dvir Markovich1b364992017-06-26 13:43:34 +0300225 /*
226 * tidy up the stack
227 */
228 mbedtls_zeroize( buf, sizeof( buf ) );
229 mbedtls_zeroize( tmp, sizeof( tmp ) );
230 mbedtls_zeroize( key, sizeof( key ) );
231 mbedtls_zeroize( chain, sizeof( chain ) );
232 if( 0 != ret )
233 {
234 /*
235 * wipe partial seed from memory
236 */
237 mbedtls_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
238 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200239
Dvir Markovich1b364992017-06-26 13:43:34 +0300240 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000241}
242
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200243static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
244 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000245{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200246 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000247 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000248 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300249 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000250
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200251 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000252
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200253 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000254 {
255 /*
256 * Increase counter
257 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200258 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000259 if( ++ctx->counter[i - 1] != 0 )
260 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000261
262 /*
263 * Crypt counter block
264 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300265 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200266 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000267
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200268 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000269 }
270
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200271 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000272 tmp[i] ^= data[i];
273
274 /*
275 * Update key and counter
276 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300277 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200278 goto exit;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200279 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000280
Gilles Peskined324c592018-09-11 15:34:17 +0200281exit:
282 mbedtls_zeroize( tmp, sizeof( tmp ) );
283 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000284}
285
Gilles Peskine9ce29722018-09-11 16:41:54 +0200286int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
287 const unsigned char *additional,
288 size_t add_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000289{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200290 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Gilles Peskine9ce29722018-09-11 16:41:54 +0200291 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000292
Gilles Peskine9ce29722018-09-11 16:41:54 +0200293 if( add_len == 0 )
294 return( 0 );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100295
Gilles Peskine9ce29722018-09-11 16:41:54 +0200296 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
297 goto exit;
298 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
299 goto exit;
300
301exit:
302 mbedtls_zeroize( add_input, sizeof( add_input ) );
303 return( ret );
304}
305
306/* Deprecated function, kept for backward compatibility. */
307void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
308 const unsigned char *additional,
309 size_t add_len )
310{
311 /* MAX_INPUT would be more logical here, but we have to match
312 * block_cipher_df()'s limits since we can't propagate errors */
313 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
314 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
315 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000316}
317
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200318int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000319 const unsigned char *additional, size_t len )
320{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200321 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000322 size_t seedlen = 0;
Dvir Markovich1b364992017-06-26 13:43:34 +0300323 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000324
Andres Amaya Garcia6a543362017-01-17 23:04:22 +0000325 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
326 len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200327 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000328
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200329 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000330
331 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200332 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000333 */
334 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
335 ctx->entropy_len ) )
336 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200337 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000338 }
339
340 seedlen += ctx->entropy_len;
341
342 /*
343 * Add additional data
344 */
345 if( additional && len )
346 {
347 memcpy( seed + seedlen, additional, len );
348 seedlen += len;
349 }
350
351 /*
352 * Reduce to 384 bits
353 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300354 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200355 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000356
357 /*
358 * Update state
359 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300360 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200361 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000362 ctx->reseed_counter = 1;
363
Gilles Peskined324c592018-09-11 15:34:17 +0200364exit:
365 mbedtls_zeroize( seed, sizeof( seed ) );
366 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000367}
Paul Bakker9af723c2014-05-01 13:03:14 +0200368
Gilles Peskineb729e1b2019-10-04 12:15:55 +0200369int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
370 int (*f_entropy)(void *, unsigned char *, size_t),
371 void *p_entropy,
372 const unsigned char *custom,
373 size_t len )
Gilles Peskine845ac102019-10-02 20:31:54 +0200374{
375 int ret;
376 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
377
378 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
379
Gilles Peskine6e2cf252021-02-09 18:44:02 +0100380 /* The mutex is initialized iff f_entropy is set. */
Gilles Peskine085b69f2021-01-30 13:05:32 +0100381#if defined(MBEDTLS_THREADING_C)
382 mbedtls_mutex_init( &ctx->mutex );
383#endif
384
Gilles Peskine845ac102019-10-02 20:31:54 +0200385 mbedtls_aes_init( &ctx->aes_ctx );
386
387 ctx->f_entropy = f_entropy;
388 ctx->p_entropy = p_entropy;
389
Gilles Peskineb729e1b2019-10-04 12:15:55 +0200390 if( ctx->entropy_len == 0 )
391 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskine845ac102019-10-02 20:31:54 +0200392
393 /*
394 * Initialize with an empty key
395 */
396 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
397 {
398 return( ret );
399 }
400
401 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
402 {
403 return( ret );
404 }
405 return( 0 );
406}
407
Gilles Peskineb729e1b2019-10-04 12:15:55 +0200408/* Backward compatibility wrapper */
409int mbedtls_ctr_drbg_seed_entropy_len(
410 mbedtls_ctr_drbg_context *ctx,
411 int (*f_entropy)(void *, unsigned char *, size_t), void *p_entropy,
412 const unsigned char *custom, size_t len,
413 size_t entropy_len )
Gilles Peskine845ac102019-10-02 20:31:54 +0200414{
Gilles Peskineb729e1b2019-10-04 12:15:55 +0200415 mbedtls_ctr_drbg_set_entropy_len( ctx, entropy_len );
416 return( mbedtls_ctr_drbg_seed( ctx, f_entropy, p_entropy, custom, len ) );
Gilles Peskine845ac102019-10-02 20:31:54 +0200417}
418
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200419int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000420 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000421 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000422{
423 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200424 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
425 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000426 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200427 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000428 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000429 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000430
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200431 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
432 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000433
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200434 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
435 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000436
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200437 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000438
439 if( ctx->reseed_counter > ctx->reseed_interval ||
440 ctx->prediction_resistance )
441 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200442 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300443 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000444 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300445 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000446 add_len = 0;
447 }
448
449 if( add_len > 0 )
450 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300451 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200452 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300453 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200454 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000455 }
456
457 while( output_len > 0 )
458 {
459 /*
460 * Increase counter
461 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000463 if( ++ctx->counter[i - 1] != 0 )
464 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000465
466 /*
467 * Crypt counter block
468 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300469 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200470 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000471
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200472 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200473 output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000474 /*
475 * Copy random block to destination
476 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000477 memcpy( p, tmp, use_len );
478 p += use_len;
479 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000480 }
481
Dvir Markovich1b364992017-06-26 13:43:34 +0300482 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200483 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000484
485 ctx->reseed_counter++;
486
Gilles Peskined324c592018-09-11 15:34:17 +0200487exit:
488 mbedtls_zeroize( add_input, sizeof( add_input ) );
489 mbedtls_zeroize( tmp, sizeof( tmp ) );
Gilles Peskineb2be1fc2019-11-28 09:45:32 +0100490 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000491}
492
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200493int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000494{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100495 int ret;
496 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
497
498#if defined(MBEDTLS_THREADING_C)
499 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
500 return( ret );
501#endif
502
503 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
504
505#if defined(MBEDTLS_THREADING_C)
506 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
507 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
508#endif
509
510 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000511}
512
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200513#if defined(MBEDTLS_FS_IO)
514int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000515{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200516 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000517 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200518 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000519
520 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200521 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000522
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200523 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200524 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000525
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200526 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200527 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100528 else
529 ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000530
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100531exit:
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100532 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200533
Paul Bakkerfc754a92011-12-05 13:23:51 +0000534 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200535 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000536}
537
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200538int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000539{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100540 int ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000541 FILE *f;
542 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200543 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000544
545 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200546 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000547
548 fseek( f, 0, SEEK_END );
549 n = (size_t) ftell( f );
550 fseek( f, 0, SEEK_SET );
551
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200552 if( n > MBEDTLS_CTR_DRBG_MAX_INPUT )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100553 {
554 fclose( f );
555 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
556 }
557
558 if( fread( buf, 1, n, f ) != n )
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100559 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
560 else
Gilles Peskine9ce29722018-09-11 16:41:54 +0200561 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000562
Paul Bakkerfc754a92011-12-05 13:23:51 +0000563 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200564
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100565 mbedtls_zeroize( buf, sizeof( buf ) );
566
567 if( ret != 0 )
568 return( ret );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200569
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200570 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000571}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200572#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000573
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200574#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000575
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000576static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000577 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
578 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
579 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
580 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
581 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
582 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
583 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
584 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
585 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
586 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
587 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
588 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
589
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000590static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000591 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
592 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
593 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
594 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
595 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
596 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
597 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
598 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
599
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100600static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000601 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
602 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
603
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100604static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000605 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
606 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
607
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100608static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000609 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
610 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
611
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100612static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000613 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
614 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
615
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100616static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200617static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
618 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000619{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100620 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000621 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100622 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000623 return( 0 );
624}
625
Paul Bakker7dc4c442014-02-01 22:50:26 +0100626#define CHK( c ) if( (c) != 0 ) \
627 { \
628 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200629 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100630 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100631 }
632
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000633/*
634 * Checkup routine
635 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200636int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000637{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200638 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000639 unsigned char buf[16];
640
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200641 mbedtls_ctr_drbg_init( &ctx );
642
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000643 /*
644 * Based on a NIST CTR_DRBG test vector (PR = True)
645 */
646 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200647 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000648
649 test_offset = 0;
Gilles Peskineb729e1b2019-10-04 12:15:55 +0200650 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
651 CHK( mbedtls_ctr_drbg_seed( &ctx,
652 ctr_drbg_self_test_entropy,
653 (void *) entropy_source_pr,
654 nonce_pers_pr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200655 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
656 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
657 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
658 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000659
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100660 mbedtls_ctr_drbg_free( &ctx );
661
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000662 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200663 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000664
665 /*
666 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
667 */
668 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200669 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000670
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100671 mbedtls_ctr_drbg_init( &ctx );
672
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000673 test_offset = 0;
Gilles Peskineb729e1b2019-10-04 12:15:55 +0200674 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
675 CHK( mbedtls_ctr_drbg_seed( &ctx,
676 ctr_drbg_self_test_entropy,
677 (void *) entropy_source_nopr,
678 nonce_pers_nopr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200679 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
680 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
681 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100682 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000683
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100684 mbedtls_ctr_drbg_free( &ctx );
685
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000686 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200687 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000688
689 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200690 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000691
692 return( 0 );
693}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200694#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000695
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200696#endif /* MBEDTLS_CTR_DRBG_C */