blob: ff532a0134eb44a7664427430e4f0fa95f96736f [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
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 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200491 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100492 else
493 ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000494
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100495exit:
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100496 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200497
Paul Bakkerfc754a92011-12-05 13:23:51 +0000498 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200499 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000500}
501
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200502int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000503{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100504 int ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000505 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 )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100517 {
518 fclose( f );
519 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
520 }
521
522 if( fread( buf, 1, n, f ) != n )
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100523 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
524 else
525 mbedtls_ctr_drbg_update( ctx, buf, n );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000526
Paul Bakkerfc754a92011-12-05 13:23:51 +0000527 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200528
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100529 mbedtls_zeroize( buf, sizeof( buf ) );
530
531 if( ret != 0 )
532 return( ret );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200533
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200534 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000535}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200536#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000537
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200538#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000539
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000540static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000541 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
542 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
543 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
544 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
545 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
546 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
547 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
548 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
549 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
550 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
551 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
552 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
553
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000554static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000555 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
556 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
557 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
558 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
559 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
560 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
561 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
562 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
563
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100564static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000565 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
566 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
567
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100568static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000569 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
570 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
571
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100572static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000573 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
574 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
575
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100576static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000577 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
578 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
579
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100580static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200581static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
582 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000583{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100584 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000585 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100586 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000587 return( 0 );
588}
589
Paul Bakker7dc4c442014-02-01 22:50:26 +0100590#define CHK( c ) if( (c) != 0 ) \
591 { \
592 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200593 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100594 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100595 }
596
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000597/*
598 * Checkup routine
599 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200600int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000601{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200602 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000603 unsigned char buf[16];
604
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200605 mbedtls_ctr_drbg_init( &ctx );
606
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000607 /*
608 * Based on a NIST CTR_DRBG test vector (PR = True)
609 */
610 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200611 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000612
613 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200614 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000615 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200616 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
617 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
618 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
619 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000620
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100621 mbedtls_ctr_drbg_free( &ctx );
622
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000623 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200624 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000625
626 /*
627 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
628 */
629 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200630 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000631
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100632 mbedtls_ctr_drbg_init( &ctx );
633
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000634 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200635 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000636 (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200637 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
638 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
639 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100640 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000641
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100642 mbedtls_ctr_drbg_free( &ctx );
643
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000644 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200645 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000646
647 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200648 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000649
650 return( 0 );
651}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200652#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000653
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200654#endif /* MBEDTLS_CTR_DRBG_C */