blob: 0638354317da2b11e1092029ad7c05e5d3c12930 [file] [log] [blame]
Paul Bakker0e04d0e2011-11-27 14:46:59 +00001/*
2 * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakker0e04d0e2011-11-27 14:46:59 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000020 */
21/*
Paul Sokolovsky8d6d8c82018-02-10 11:11:41 +020022 * The NIST SP 800-90 DRBGs are described in the following publication.
Paul Bakker0e04d0e2011-11-27 14:46:59 +000023 *
24 * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
25 */
26
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020027#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000028#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020029#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020030#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020031#endif
Paul Bakker0e04d0e2011-11-27 14:46:59 +000032
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020033#if defined(MBEDTLS_CTR_DRBG_C)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000034
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000035#include "mbedtls/ctr_drbg.h"
Paul Bakker0e04d0e2011-11-27 14:46:59 +000036
Rich Evans00ab4702015-02-06 13:43:58 +000037#include <string.h>
38
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020039#if defined(MBEDTLS_FS_IO)
Paul Bakkerfc754a92011-12-05 13:23:51 +000040#include <stdio.h>
41#endif
42
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020043#if defined(MBEDTLS_SELF_TEST)
44#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000045#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010046#else
Rich Evans00ab4702015-02-06 13:43:58 +000047#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020048#define mbedtls_printf printf
49#endif /* MBEDTLS_PLATFORM_C */
50#endif /* MBEDTLS_SELF_TEST */
Paul Bakker7dc4c442014-02-01 22:50:26 +010051
Paul Bakkerfff03662014-06-18 16:21:25 +020052/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020053static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakkerfff03662014-06-18 16:21:25 +020054 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
55}
56
Paul Bakker18d32912011-12-10 21:42:49 +000057/*
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020058 * CTR_DRBG context initialization
59 */
60void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
61{
62 memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010063
64#if defined(MBEDTLS_THREADING_C)
65 mbedtls_mutex_init( &ctx->mutex );
66#endif
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020067}
68
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020069void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
Paul Bakkerfff03662014-06-18 16:21:25 +020070{
71 if( ctx == NULL )
72 return;
73
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010074#if defined(MBEDTLS_THREADING_C)
75 mbedtls_mutex_free( &ctx->mutex );
76#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020077 mbedtls_aes_free( &ctx->aes_ctx );
78 mbedtls_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Paul Bakkerfff03662014-06-18 16:21:25 +020079}
80
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020081void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000082{
83 ctx->prediction_resistance = resistance;
84}
85
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020086void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000087{
88 ctx->entropy_len = len;
89}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +020090
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020091void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000092{
93 ctx->reseed_interval = interval;
94}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +020095
96static int block_cipher_df( unsigned char *output,
97 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000098{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020099 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
100 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
101 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
102 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100103 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200104 mbedtls_aes_context aes_ctx;
Dvir Markovich1b364992017-06-26 13:43:34 +0300105 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000106
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200107 int i, j;
108 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000109
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200110 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
111 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100112
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200113 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
114 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000115
116 /*
117 * Construct IV (16 bytes) and S in buffer
118 * IV = Counter (in 32-bits) padded to 16 with zeroes
119 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
120 * data || 0x80
121 * (Total is padded to a multiple of 16-bytes with zeroes)
122 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200123 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000124 *p++ = ( data_len >> 24 ) & 0xff;
125 *p++ = ( data_len >> 16 ) & 0xff;
126 *p++ = ( data_len >> 8 ) & 0xff;
127 *p++ = ( data_len ) & 0xff;
128 p += 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200129 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000130 memcpy( p, data, data_len );
131 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000132
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200133 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000134
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200135 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000136 key[i] = i;
137
Dvir Markovich1b364992017-06-26 13:43:34 +0300138 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
139 {
140 goto exit;
141 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000142
143 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200144 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000145 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200146 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000147 {
148 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200149 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000150 use_len = buf_len;
151
152 while( use_len > 0 )
153 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200154 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000155 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200156 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
157 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
158 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000159
Dvir Markovich1b364992017-06-26 13:43:34 +0300160 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ) ) != 0 )
161 {
162 goto exit;
163 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000164 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200165
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200166 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000167
168 /*
169 * Update IV
170 */
171 buf[3]++;
172 }
173
174 /*
175 * Do final encryption with reduced data
176 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300177 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
178 {
179 goto exit;
180 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200181 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000182 p = output;
183
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200184 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000185 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300186 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) ) != 0 )
187 {
188 goto exit;
189 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200190 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
191 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000192 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300193exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200194 mbedtls_aes_free( &aes_ctx );
Dvir Markovich1b364992017-06-26 13:43:34 +0300195 /*
196 * tidy up the stack
197 */
198 mbedtls_zeroize( buf, sizeof( buf ) );
199 mbedtls_zeroize( tmp, sizeof( tmp ) );
200 mbedtls_zeroize( key, sizeof( key ) );
201 mbedtls_zeroize( chain, sizeof( chain ) );
202 if( 0 != ret )
203 {
204 /*
205 * wipe partial seed from memory
206 */
207 mbedtls_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
208 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200209
Dvir Markovich1b364992017-06-26 13:43:34 +0300210 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000211}
212
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200213static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
214 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000215{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200216 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000217 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000218 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300219 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000220
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200221 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000222
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200223 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000224 {
225 /*
226 * Increase counter
227 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200228 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000229 if( ++ctx->counter[i - 1] != 0 )
230 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000231
232 /*
233 * Crypt counter block
234 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300235 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200236 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000237
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200238 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000239 }
240
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200241 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000242 tmp[i] ^= data[i];
243
244 /*
245 * Update key and counter
246 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300247 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200248 goto exit;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200249 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000250
Gilles Peskined324c592018-09-11 15:34:17 +0200251exit:
252 mbedtls_zeroize( tmp, sizeof( tmp ) );
253 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000254}
255
Gilles Peskine9ce29722018-09-11 16:41:54 +0200256int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
257 const unsigned char *additional,
258 size_t add_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000259{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200260 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Gilles Peskine9ce29722018-09-11 16:41:54 +0200261 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000262
Gilles Peskine9ce29722018-09-11 16:41:54 +0200263 if( add_len == 0 )
264 return( 0 );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100265
Gilles Peskine9ce29722018-09-11 16:41:54 +0200266 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
267 goto exit;
268 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
269 goto exit;
270
271exit:
272 mbedtls_zeroize( add_input, sizeof( add_input ) );
273 return( ret );
274}
275
276/* Deprecated function, kept for backward compatibility. */
277void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
278 const unsigned char *additional,
279 size_t add_len )
280{
281 /* MAX_INPUT would be more logical here, but we have to match
282 * block_cipher_df()'s limits since we can't propagate errors */
283 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
284 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
285 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000286}
287
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200288int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000289 const unsigned char *additional, size_t len )
290{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200291 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000292 size_t seedlen = 0;
Dvir Markovich1b364992017-06-26 13:43:34 +0300293 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000294
Andres Amaya Garcia6a543362017-01-17 23:04:22 +0000295 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
296 len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200297 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000298
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200299 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000300
301 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200302 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000303 */
304 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
305 ctx->entropy_len ) )
306 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200307 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000308 }
309
310 seedlen += ctx->entropy_len;
311
312 /*
313 * Add additional data
314 */
315 if( additional && len )
316 {
317 memcpy( seed + seedlen, additional, len );
318 seedlen += len;
319 }
320
321 /*
322 * Reduce to 384 bits
323 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300324 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200325 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000326
327 /*
328 * Update state
329 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300330 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200331 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000332 ctx->reseed_counter = 1;
333
Gilles Peskined324c592018-09-11 15:34:17 +0200334exit:
335 mbedtls_zeroize( seed, sizeof( seed ) );
336 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000337}
Paul Bakker9af723c2014-05-01 13:03:14 +0200338
Gilles Peskineb729e1b2019-10-04 12:15:55 +0200339int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
340 int (*f_entropy)(void *, unsigned char *, size_t),
341 void *p_entropy,
342 const unsigned char *custom,
343 size_t len )
Gilles Peskine845ac102019-10-02 20:31:54 +0200344{
345 int ret;
346 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
347
348 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
349
350 mbedtls_aes_init( &ctx->aes_ctx );
351
352 ctx->f_entropy = f_entropy;
353 ctx->p_entropy = p_entropy;
354
Gilles Peskineb729e1b2019-10-04 12:15:55 +0200355 if( ctx->entropy_len == 0 )
356 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskine845ac102019-10-02 20:31:54 +0200357 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
358
359 /*
360 * Initialize with an empty key
361 */
362 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
363 {
364 return( ret );
365 }
366
367 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
368 {
369 return( ret );
370 }
371 return( 0 );
372}
373
Gilles Peskineb729e1b2019-10-04 12:15:55 +0200374/* Backward compatibility wrapper */
375int mbedtls_ctr_drbg_seed_entropy_len(
376 mbedtls_ctr_drbg_context *ctx,
377 int (*f_entropy)(void *, unsigned char *, size_t), void *p_entropy,
378 const unsigned char *custom, size_t len,
379 size_t entropy_len )
Gilles Peskine845ac102019-10-02 20:31:54 +0200380{
Gilles Peskineb729e1b2019-10-04 12:15:55 +0200381 mbedtls_ctr_drbg_set_entropy_len( ctx, entropy_len );
382 return( mbedtls_ctr_drbg_seed( ctx, f_entropy, p_entropy, custom, len ) );
Gilles Peskine845ac102019-10-02 20:31:54 +0200383}
384
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200385int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000386 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000387 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000388{
389 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200390 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
391 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000392 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200393 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000394 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000395 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000396
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200397 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
398 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000399
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200400 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
401 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000402
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200403 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000404
405 if( ctx->reseed_counter > ctx->reseed_interval ||
406 ctx->prediction_resistance )
407 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200408 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300409 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000410 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300411 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000412 add_len = 0;
413 }
414
415 if( add_len > 0 )
416 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300417 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200418 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300419 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200420 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000421 }
422
423 while( output_len > 0 )
424 {
425 /*
426 * Increase counter
427 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200428 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000429 if( ++ctx->counter[i - 1] != 0 )
430 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000431
432 /*
433 * Crypt counter block
434 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300435 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200436 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000437
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200438 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200439 output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000440 /*
441 * Copy random block to destination
442 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000443 memcpy( p, tmp, use_len );
444 p += use_len;
445 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000446 }
447
Dvir Markovich1b364992017-06-26 13:43:34 +0300448 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200449 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000450
451 ctx->reseed_counter++;
452
Gilles Peskined324c592018-09-11 15:34:17 +0200453exit:
454 mbedtls_zeroize( add_input, sizeof( add_input ) );
455 mbedtls_zeroize( tmp, sizeof( tmp ) );
Gilles Peskineb2be1fc2019-11-28 09:45:32 +0100456 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000457}
458
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200459int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000460{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100461 int ret;
462 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
463
464#if defined(MBEDTLS_THREADING_C)
465 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
466 return( ret );
467#endif
468
469 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
470
471#if defined(MBEDTLS_THREADING_C)
472 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
473 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
474#endif
475
476 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000477}
478
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200479#if defined(MBEDTLS_FS_IO)
480int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000481{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200482 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000483 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200484 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000485
486 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200487 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000488
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200489 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200490 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000491
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200492 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200493 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100494 else
495 ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000496
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100497exit:
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100498 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200499
Paul Bakkerfc754a92011-12-05 13:23:51 +0000500 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200501 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000502}
503
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200504int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000505{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100506 int ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000507 FILE *f;
508 size_t n;
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, "rb" ) ) == 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
514 fseek( f, 0, SEEK_END );
515 n = (size_t) ftell( f );
516 fseek( f, 0, SEEK_SET );
517
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200518 if( n > MBEDTLS_CTR_DRBG_MAX_INPUT )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100519 {
520 fclose( f );
521 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
522 }
523
524 if( fread( buf, 1, n, f ) != n )
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100525 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
526 else
Gilles Peskine9ce29722018-09-11 16:41:54 +0200527 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000528
Paul Bakkerfc754a92011-12-05 13:23:51 +0000529 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200530
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100531 mbedtls_zeroize( buf, sizeof( buf ) );
532
533 if( ret != 0 )
534 return( ret );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200535
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200536 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000537}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200538#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000539
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200540#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000541
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000542static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000543 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
544 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
545 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
546 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
547 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
548 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
549 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
550 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
551 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
552 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
553 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
554 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
555
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000556static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000557 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
558 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
559 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
560 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
561 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
562 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
563 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
564 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
565
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100566static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000567 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
568 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
569
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100570static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000571 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
572 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
573
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100574static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000575 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
576 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
577
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100578static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000579 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
580 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
581
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100582static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200583static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
584 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000585{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100586 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000587 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100588 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000589 return( 0 );
590}
591
Paul Bakker7dc4c442014-02-01 22:50:26 +0100592#define CHK( c ) if( (c) != 0 ) \
593 { \
594 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200595 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100596 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100597 }
598
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000599/*
600 * Checkup routine
601 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200602int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000603{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200604 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000605 unsigned char buf[16];
606
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200607 mbedtls_ctr_drbg_init( &ctx );
608
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000609 /*
610 * Based on a NIST CTR_DRBG test vector (PR = True)
611 */
612 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200613 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000614
615 test_offset = 0;
Gilles Peskineb729e1b2019-10-04 12:15:55 +0200616 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
617 CHK( mbedtls_ctr_drbg_seed( &ctx,
618 ctr_drbg_self_test_entropy,
619 (void *) entropy_source_pr,
620 nonce_pers_pr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200621 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
622 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
623 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
624 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000625
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100626 mbedtls_ctr_drbg_free( &ctx );
627
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000628 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200629 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000630
631 /*
632 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
633 */
634 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200635 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000636
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100637 mbedtls_ctr_drbg_init( &ctx );
638
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000639 test_offset = 0;
Gilles Peskineb729e1b2019-10-04 12:15:55 +0200640 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
641 CHK( mbedtls_ctr_drbg_seed( &ctx,
642 ctr_drbg_self_test_entropy,
643 (void *) entropy_source_nopr,
644 nonce_pers_nopr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200645 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
646 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
647 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100648 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000649
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100650 mbedtls_ctr_drbg_free( &ctx );
651
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000652 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200653 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000654
655 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200656 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000657
658 return( 0 );
659}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200660#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000661
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200662#endif /* MBEDTLS_CTR_DRBG_C */