blob: a99ec005a875f4b20616ea8fd4bdb7863d515267 [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 Peskine845ac102019-10-02 20:31:54 +0200339/*
340 * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow
341 * NIST tests to succeed (which require known length fixed entropy)
342 */
343int mbedtls_ctr_drbg_seed_entropy_len(
344 mbedtls_ctr_drbg_context *ctx,
345 int (*f_entropy)(void *, unsigned char *, size_t),
346 void *p_entropy,
347 const unsigned char *custom,
348 size_t len,
349 size_t entropy_len )
350{
351 int ret;
352 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
353
354 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
355
356 mbedtls_aes_init( &ctx->aes_ctx );
357
358 ctx->f_entropy = f_entropy;
359 ctx->p_entropy = p_entropy;
360
361 ctx->entropy_len = entropy_len;
362 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
363
364 /*
365 * Initialize with an empty key
366 */
367 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
368 {
369 return( ret );
370 }
371
372 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
373 {
374 return( ret );
375 }
376 return( 0 );
377}
378
379int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
380 int (*f_entropy)(void *, unsigned char *, size_t),
381 void *p_entropy,
382 const unsigned char *custom,
383 size_t len )
384{
385 return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy, custom, len,
386 MBEDTLS_CTR_DRBG_ENTROPY_LEN ) );
387}
388
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200389int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000390 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000391 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000392{
393 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200394 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
395 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000396 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200397 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000398 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000399 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000400
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200401 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
402 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000403
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200404 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
405 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000406
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200407 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000408
409 if( ctx->reseed_counter > ctx->reseed_interval ||
410 ctx->prediction_resistance )
411 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200412 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300413 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000414 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300415 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000416 add_len = 0;
417 }
418
419 if( add_len > 0 )
420 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300421 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200422 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300423 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200424 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000425 }
426
427 while( output_len > 0 )
428 {
429 /*
430 * Increase counter
431 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200432 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000433 if( ++ctx->counter[i - 1] != 0 )
434 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000435
436 /*
437 * Crypt counter block
438 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300439 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200440 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000441
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200442 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200443 output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000444 /*
445 * Copy random block to destination
446 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000447 memcpy( p, tmp, use_len );
448 p += use_len;
449 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000450 }
451
Dvir Markovich1b364992017-06-26 13:43:34 +0300452 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200453 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000454
455 ctx->reseed_counter++;
456
Gilles Peskined324c592018-09-11 15:34:17 +0200457exit:
458 mbedtls_zeroize( add_input, sizeof( add_input ) );
459 mbedtls_zeroize( tmp, sizeof( tmp ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000460 return( 0 );
461}
462
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200463int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000464{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100465 int ret;
466 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
467
468#if defined(MBEDTLS_THREADING_C)
469 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
470 return( ret );
471#endif
472
473 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
474
475#if defined(MBEDTLS_THREADING_C)
476 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
477 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
478#endif
479
480 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000481}
482
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200483#if defined(MBEDTLS_FS_IO)
484int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000485{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200486 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000487 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200488 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000489
490 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200491 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000492
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200493 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200494 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000495
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200496 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200497 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100498 else
499 ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000500
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100501exit:
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100502 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200503
Paul Bakkerfc754a92011-12-05 13:23:51 +0000504 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200505 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000506}
507
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200508int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000509{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100510 int ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000511 FILE *f;
512 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200513 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000514
515 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200516 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000517
518 fseek( f, 0, SEEK_END );
519 n = (size_t) ftell( f );
520 fseek( f, 0, SEEK_SET );
521
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200522 if( n > MBEDTLS_CTR_DRBG_MAX_INPUT )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100523 {
524 fclose( f );
525 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
526 }
527
528 if( fread( buf, 1, n, f ) != n )
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100529 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
530 else
Gilles Peskine9ce29722018-09-11 16:41:54 +0200531 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000532
Paul Bakkerfc754a92011-12-05 13:23:51 +0000533 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200534
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100535 mbedtls_zeroize( buf, sizeof( buf ) );
536
537 if( ret != 0 )
538 return( ret );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200539
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200540 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000541}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200542#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000543
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200544#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000545
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000546static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000547 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
548 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
549 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
550 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
551 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
552 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
553 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
554 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
555 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
556 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
557 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
558 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
559
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000560static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000561 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
562 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
563 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
564 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
565 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
566 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
567 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
568 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
569
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100570static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000571 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
572 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
573
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100574static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000575 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
576 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
577
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100578static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000579 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
580 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
581
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100582static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000583 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
584 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
585
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100586static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200587static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
588 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000589{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100590 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000591 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100592 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000593 return( 0 );
594}
595
Paul Bakker7dc4c442014-02-01 22:50:26 +0100596#define CHK( c ) if( (c) != 0 ) \
597 { \
598 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200599 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100600 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100601 }
602
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000603/*
604 * Checkup routine
605 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200606int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000607{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200608 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000609 unsigned char buf[16];
610
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200611 mbedtls_ctr_drbg_init( &ctx );
612
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000613 /*
614 * Based on a NIST CTR_DRBG test vector (PR = True)
615 */
616 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200617 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000618
619 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200620 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000621 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200622 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
623 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
624 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
625 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000626
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100627 mbedtls_ctr_drbg_free( &ctx );
628
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000629 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200630 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000631
632 /*
633 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
634 */
635 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200636 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000637
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100638 mbedtls_ctr_drbg_init( &ctx );
639
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000640 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200641 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000642 (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200643 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
644 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
645 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100646 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000647
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100648 mbedtls_ctr_drbg_free( &ctx );
649
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000650 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200651 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000652
653 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200654 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000655
656 return( 0 );
657}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200658#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000659
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200660#endif /* MBEDTLS_CTR_DRBG_C */