blob: 2d2da2434dadd5885ca8932545f813d8f9cb956b [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/*
22 * The NIST SP 800-90 DRBGs are described in the following publucation.
23 *
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
69/*
Simon Butcher71c7ac52016-05-10 23:47:30 +010070 * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow
71 * NIST tests to succeed (which require known length fixed entropy)
Paul Bakker18d32912011-12-10 21:42:49 +000072 */
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020073int mbedtls_ctr_drbg_seed_entropy_len(
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020074 mbedtls_ctr_drbg_context *ctx,
Paul Bakker0e04d0e2011-11-27 14:46:59 +000075 int (*f_entropy)(void *, unsigned char *, size_t),
76 void *p_entropy,
Paul Bakker1bc9efc2011-12-03 11:29:32 +000077 const unsigned char *custom,
Paul Bakker18d32912011-12-10 21:42:49 +000078 size_t len,
79 size_t entropy_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000080{
81 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020082 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Paul Bakker0e04d0e2011-11-27 14:46:59 +000083
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020084 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000085
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020086 mbedtls_aes_init( &ctx->aes_ctx );
Paul Bakkerc7ea99a2014-06-18 11:12:03 +020087
Paul Bakker0e04d0e2011-11-27 14:46:59 +000088 ctx->f_entropy = f_entropy;
89 ctx->p_entropy = p_entropy;
90
Paul Bakker18d32912011-12-10 21:42:49 +000091 ctx->entropy_len = entropy_len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020092 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
Paul Bakker0e04d0e2011-11-27 14:46:59 +000093
94 /*
95 * Initialize with an empty key
96 */
Dvir Markovich1b364992017-06-26 13:43:34 +030097 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
98 {
99 return( ret );
100 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000101
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200102 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300103 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000104 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300105 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000106 return( 0 );
107}
108
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200109int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker18d32912011-12-10 21:42:49 +0000110 int (*f_entropy)(void *, unsigned char *, size_t),
111 void *p_entropy,
112 const unsigned char *custom,
113 size_t len )
114{
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200115 return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy, custom, len,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200116 MBEDTLS_CTR_DRBG_ENTROPY_LEN ) );
Paul Bakker18d32912011-12-10 21:42:49 +0000117}
118
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200119void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
Paul Bakkerfff03662014-06-18 16:21:25 +0200120{
121 if( ctx == NULL )
122 return;
123
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100124#if defined(MBEDTLS_THREADING_C)
125 mbedtls_mutex_free( &ctx->mutex );
126#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200127 mbedtls_aes_free( &ctx->aes_ctx );
128 mbedtls_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Paul Bakkerfff03662014-06-18 16:21:25 +0200129}
130
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200131void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000132{
133 ctx->prediction_resistance = resistance;
134}
135
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200136void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000137{
138 ctx->entropy_len = len;
139}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200140
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200141void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000142{
143 ctx->reseed_interval = interval;
144}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200145
146static int block_cipher_df( unsigned char *output,
147 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000148{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200149 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
150 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
151 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
152 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100153 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200154 mbedtls_aes_context aes_ctx;
Dvir Markovich1b364992017-06-26 13:43:34 +0300155 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000156
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200157 int i, j;
158 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000159
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200160 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
161 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100162
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200163 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
164 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000165
166 /*
167 * Construct IV (16 bytes) and S in buffer
168 * IV = Counter (in 32-bits) padded to 16 with zeroes
169 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
170 * data || 0x80
171 * (Total is padded to a multiple of 16-bytes with zeroes)
172 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200173 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000174 *p++ = ( data_len >> 24 ) & 0xff;
175 *p++ = ( data_len >> 16 ) & 0xff;
176 *p++ = ( data_len >> 8 ) & 0xff;
177 *p++ = ( data_len ) & 0xff;
178 p += 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200179 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000180 memcpy( p, data, data_len );
181 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000182
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200183 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000184
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200185 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000186 key[i] = i;
187
Dvir Markovich1b364992017-06-26 13:43:34 +0300188 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
189 {
190 goto exit;
191 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000192
193 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200194 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000195 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200196 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000197 {
198 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200199 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000200 use_len = buf_len;
201
202 while( use_len > 0 )
203 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200204 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000205 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200206 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
207 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
208 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000209
Dvir Markovich1b364992017-06-26 13:43:34 +0300210 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ) ) != 0 )
211 {
212 goto exit;
213 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000214 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200215
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200216 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000217
218 /*
219 * Update IV
220 */
221 buf[3]++;
222 }
223
224 /*
225 * Do final encryption with reduced data
226 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300227 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
228 {
229 goto exit;
230 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200231 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000232 p = output;
233
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200234 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000235 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300236 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) ) != 0 )
237 {
238 goto exit;
239 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200240 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
241 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000242 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300243exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200244 mbedtls_aes_free( &aes_ctx );
Dvir Markovich1b364992017-06-26 13:43:34 +0300245 /*
246 * tidy up the stack
247 */
248 mbedtls_zeroize( buf, sizeof( buf ) );
249 mbedtls_zeroize( tmp, sizeof( tmp ) );
250 mbedtls_zeroize( key, sizeof( key ) );
251 mbedtls_zeroize( chain, sizeof( chain ) );
252 if( 0 != ret )
253 {
254 /*
255 * wipe partial seed from memory
256 */
257 mbedtls_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
258 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200259
Dvir Markovich1b364992017-06-26 13:43:34 +0300260 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000261}
262
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200263static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
264 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000265{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200266 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000267 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000268 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300269 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000270
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200271 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000272
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200273 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000274 {
275 /*
276 * Increase counter
277 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200278 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000279 if( ++ctx->counter[i - 1] != 0 )
280 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000281
282 /*
283 * Crypt counter block
284 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300285 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 )
286 {
287 return( ret );
288 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000289
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200290 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000291 }
292
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200293 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000294 tmp[i] ^= data[i];
295
296 /*
297 * Update key and counter
298 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300299 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
300 {
301 return( ret );
302 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200303 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000304
305 return( 0 );
306}
307
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200308void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000309 const unsigned char *additional, size_t add_len )
310{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200311 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000312
313 if( add_len > 0 )
314 {
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100315 /* MAX_INPUT would be more logical here, but we have to match
316 * block_cipher_df()'s limits since we can't propagate errors */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200317 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
318 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100319
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000320 block_cipher_df( add_input, additional, add_len );
321 ctr_drbg_update_internal( ctx, add_input );
322 }
323}
324
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200325int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000326 const unsigned char *additional, size_t len )
327{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200328 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000329 size_t seedlen = 0;
Dvir Markovich1b364992017-06-26 13:43:34 +0300330 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000331
Andres Amaya Garcia6a543362017-01-17 23:04:22 +0000332 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
333 len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200334 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000335
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200336 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000337
338 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200339 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000340 */
341 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
342 ctx->entropy_len ) )
343 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200344 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000345 }
346
347 seedlen += ctx->entropy_len;
348
349 /*
350 * Add additional data
351 */
352 if( additional && len )
353 {
354 memcpy( seed + seedlen, additional, len );
355 seedlen += len;
356 }
357
358 /*
359 * Reduce to 384 bits
360 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300361 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
362 {
363 return( ret );
364 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000365
366 /*
367 * Update state
368 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300369 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
370 {
371 return( ret );
372 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000373 ctx->reseed_counter = 1;
374
375 return( 0 );
376}
Paul Bakker9af723c2014-05-01 13:03:14 +0200377
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200378int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000379 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000380 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000381{
382 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200383 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
384 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000385 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200386 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000387 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000388 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000389
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200390 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
391 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000392
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200393 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
394 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000395
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200396 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000397
398 if( ctx->reseed_counter > ctx->reseed_interval ||
399 ctx->prediction_resistance )
400 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200401 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300402 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000403 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300404 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000405 add_len = 0;
406 }
407
408 if( add_len > 0 )
409 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300410 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
411 {
412 return( ret );
413 }
414 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
415 {
416 return( ret );
417 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000418 }
419
420 while( output_len > 0 )
421 {
422 /*
423 * Increase counter
424 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200425 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000426 if( ++ctx->counter[i - 1] != 0 )
427 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000428
429 /*
430 * Crypt counter block
431 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300432 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 )
433 {
434 return( ret );
435 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000436
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200437 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200438 output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000439 /*
440 * Copy random block to destination
441 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000442 memcpy( p, tmp, use_len );
443 p += use_len;
444 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000445 }
446
Dvir Markovich1b364992017-06-26 13:43:34 +0300447 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
448 {
449 return( ret );
450 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000451
452 ctx->reseed_counter++;
453
454 return( 0 );
455}
456
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200457int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000458{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100459 int ret;
460 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
461
462#if defined(MBEDTLS_THREADING_C)
463 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
464 return( ret );
465#endif
466
467 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
468
469#if defined(MBEDTLS_THREADING_C)
470 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
471 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
472#endif
473
474 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000475}
476
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200477#if defined(MBEDTLS_FS_IO)
478int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000479{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200480 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000481 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200482 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000483
484 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200485 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000486
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200487 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200488 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000489
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200490 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000491 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200492 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakker4c284c92014-03-26 15:33:05 +0100493 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000494 }
495
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200496 ret = 0;
497
498exit:
Paul Bakkerfc754a92011-12-05 13:23:51 +0000499 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200500 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000501}
502
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200503int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000504{
505 FILE *f;
506 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200507 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000508
509 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200510 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000511
512 fseek( f, 0, SEEK_END );
513 n = (size_t) ftell( f );
514 fseek( f, 0, SEEK_SET );
515
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200516 if( n > MBEDTLS_CTR_DRBG_MAX_INPUT )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200517 {
518 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200519 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200520 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000521
522 if( fread( buf, 1, n, f ) != n )
523 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100524 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200525 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000526 }
527
Paul Bakkerfc754a92011-12-05 13:23:51 +0000528 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200529
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200530 mbedtls_ctr_drbg_update( ctx, buf, n );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200531
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200532 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000533}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200534#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000535
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200536#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000537
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000538static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000539 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
540 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
541 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
542 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
543 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
544 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
545 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
546 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
547 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
548 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
549 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
550 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
551
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000552static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000553 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
554 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
555 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
556 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
557 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
558 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
559 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
560 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
561
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100562static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000563 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
564 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
565
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100566static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000567 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
568 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
569
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100570static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000571 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
572 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
573
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100574static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000575 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
576 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
577
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100578static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200579static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
580 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000581{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100582 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000583 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100584 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000585 return( 0 );
586}
587
Paul Bakker7dc4c442014-02-01 22:50:26 +0100588#define CHK( c ) if( (c) != 0 ) \
589 { \
590 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200591 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100592 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100593 }
594
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000595/*
596 * Checkup routine
597 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200598int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000599{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200600 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000601 unsigned char buf[16];
602
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200603 mbedtls_ctr_drbg_init( &ctx );
604
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000605 /*
606 * Based on a NIST CTR_DRBG test vector (PR = True)
607 */
608 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200609 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000610
611 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200612 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000613 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200614 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
615 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
616 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
617 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000618
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100619 mbedtls_ctr_drbg_free( &ctx );
620
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000621 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200622 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000623
624 /*
625 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
626 */
627 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200628 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000629
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100630 mbedtls_ctr_drbg_init( &ctx );
631
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000632 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200633 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000634 (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200635 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
636 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
637 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100638 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000639
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100640 mbedtls_ctr_drbg_free( &ctx );
641
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000642 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200643 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000644
645 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200646 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000647
648 return( 0 );
649}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200650#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000651
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200652#endif /* MBEDTLS_CTR_DRBG_C */