blob: bc5cc8f63f01939a6e693ba1d9443ab84829f4a7 [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;
90
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010091#if defined(MBEDTLS_THREADING_C)
92 mbedtls_mutex_init( &ctx->mutex );
93#endif
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020094}
95
Gavin Acquroffceb99902020-03-01 17:06:11 -080096/*
97 * This function resets CTR_DRBG context to the state immediately
98 * after initial call of mbedtls_ctr_drbg_init().
99 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200100void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
Paul Bakkerfff03662014-06-18 16:21:25 +0200101{
102 if( ctx == NULL )
103 return;
104
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100105#if defined(MBEDTLS_THREADING_C)
106 mbedtls_mutex_free( &ctx->mutex );
107#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200108 mbedtls_aes_free( &ctx->aes_ctx );
109 mbedtls_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Gavin Acquroffceb99902020-03-01 17:06:11 -0800110 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
111#if defined(MBEDTLS_THREADING_C)
112 mbedtls_mutex_init( &ctx->mutex );
113#endif
Paul Bakkerfff03662014-06-18 16:21:25 +0200114}
115
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200116void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000117{
118 ctx->prediction_resistance = resistance;
119}
120
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200121void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000122{
123 ctx->entropy_len = len;
124}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200125
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200126void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000127{
128 ctx->reseed_interval = interval;
129}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200130
131static int block_cipher_df( unsigned char *output,
132 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000133{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200134 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
135 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
136 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
137 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100138 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200139 mbedtls_aes_context aes_ctx;
Dvir Markovich1b364992017-06-26 13:43:34 +0300140 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000141
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200142 int i, j;
143 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000144
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200145 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
146 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100147
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200148 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
149 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000150
151 /*
152 * Construct IV (16 bytes) and S in buffer
153 * IV = Counter (in 32-bits) padded to 16 with zeroes
154 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
155 * data || 0x80
156 * (Total is padded to a multiple of 16-bytes with zeroes)
157 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200158 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000159 *p++ = ( data_len >> 24 ) & 0xff;
160 *p++ = ( data_len >> 16 ) & 0xff;
161 *p++ = ( data_len >> 8 ) & 0xff;
162 *p++ = ( data_len ) & 0xff;
163 p += 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200164 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000165 memcpy( p, data, data_len );
166 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000167
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200168 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000169
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200170 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000171 key[i] = i;
172
Dvir Markovich1b364992017-06-26 13:43:34 +0300173 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
174 {
175 goto exit;
176 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000177
178 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200179 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000180 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200181 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000182 {
183 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200184 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000185 use_len = buf_len;
186
187 while( use_len > 0 )
188 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200189 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000190 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200191 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
192 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
193 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000194
Dvir Markovich1b364992017-06-26 13:43:34 +0300195 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ) ) != 0 )
196 {
197 goto exit;
198 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000199 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200200
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200201 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000202
203 /*
204 * Update IV
205 */
206 buf[3]++;
207 }
208
209 /*
210 * Do final encryption with reduced data
211 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300212 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
213 {
214 goto exit;
215 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200216 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000217 p = output;
218
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200219 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000220 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300221 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) ) != 0 )
222 {
223 goto exit;
224 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200225 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
226 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000227 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300228exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200229 mbedtls_aes_free( &aes_ctx );
Dvir Markovich1b364992017-06-26 13:43:34 +0300230 /*
231 * tidy up the stack
232 */
233 mbedtls_zeroize( buf, sizeof( buf ) );
234 mbedtls_zeroize( tmp, sizeof( tmp ) );
235 mbedtls_zeroize( key, sizeof( key ) );
236 mbedtls_zeroize( chain, sizeof( chain ) );
237 if( 0 != ret )
238 {
239 /*
240 * wipe partial seed from memory
241 */
242 mbedtls_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
243 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200244
Dvir Markovich1b364992017-06-26 13:43:34 +0300245 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000246}
247
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200248static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
249 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000250{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200251 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000252 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000253 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300254 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000255
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200256 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000257
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200258 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000259 {
260 /*
261 * Increase counter
262 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200263 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000264 if( ++ctx->counter[i - 1] != 0 )
265 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000266
267 /*
268 * Crypt counter block
269 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300270 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200271 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000272
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200273 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000274 }
275
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200276 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000277 tmp[i] ^= data[i];
278
279 /*
280 * Update key and counter
281 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300282 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200283 goto exit;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200284 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000285
Gilles Peskined324c592018-09-11 15:34:17 +0200286exit:
287 mbedtls_zeroize( tmp, sizeof( tmp ) );
288 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000289}
290
Gilles Peskine9ce29722018-09-11 16:41:54 +0200291int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
292 const unsigned char *additional,
293 size_t add_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000294{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200295 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Gilles Peskine9ce29722018-09-11 16:41:54 +0200296 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000297
Gilles Peskine9ce29722018-09-11 16:41:54 +0200298 if( add_len == 0 )
299 return( 0 );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100300
Gilles Peskine9ce29722018-09-11 16:41:54 +0200301 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
302 goto exit;
303 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
304 goto exit;
305
306exit:
307 mbedtls_zeroize( add_input, sizeof( add_input ) );
308 return( ret );
309}
310
311/* Deprecated function, kept for backward compatibility. */
312void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
313 const unsigned char *additional,
314 size_t add_len )
315{
316 /* MAX_INPUT would be more logical here, but we have to match
317 * block_cipher_df()'s limits since we can't propagate errors */
318 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
319 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
320 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000321}
322
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200323int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000324 const unsigned char *additional, size_t len )
325{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200326 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000327 size_t seedlen = 0;
Dvir Markovich1b364992017-06-26 13:43:34 +0300328 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000329
Andres Amaya Garcia6a543362017-01-17 23:04:22 +0000330 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
331 len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200332 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000333
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200334 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000335
336 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200337 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000338 */
339 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
340 ctx->entropy_len ) )
341 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200342 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000343 }
344
345 seedlen += ctx->entropy_len;
346
347 /*
348 * Add additional data
349 */
350 if( additional && len )
351 {
352 memcpy( seed + seedlen, additional, len );
353 seedlen += len;
354 }
355
356 /*
357 * Reduce to 384 bits
358 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300359 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200360 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000361
362 /*
363 * Update state
364 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300365 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200366 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000367 ctx->reseed_counter = 1;
368
Gilles Peskined324c592018-09-11 15:34:17 +0200369exit:
370 mbedtls_zeroize( seed, sizeof( seed ) );
371 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000372}
Paul Bakker9af723c2014-05-01 13:03:14 +0200373
Gilles Peskineb729e1b2019-10-04 12:15:55 +0200374int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
375 int (*f_entropy)(void *, unsigned char *, size_t),
376 void *p_entropy,
377 const unsigned char *custom,
378 size_t len )
Gilles Peskine845ac102019-10-02 20:31:54 +0200379{
380 int ret;
381 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
382
383 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
384
385 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 */