blob: ec7d9a7732abc4c1095c2fb5e02d624496258855 [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é-Gonnarda658a402015-01-23 09:45:19 +00004 * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
Paul Bakker0e04d0e2011-11-27 14:46:59 +00005 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +00006 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker0e04d0e2011-11-27 14:46:59 +00007 *
Paul Bakker0e04d0e2011-11-27 14:46:59 +00008 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22/*
23 * The NIST SP 800-90 DRBGs are described in the following publucation.
24 *
25 * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
26 */
27
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020028#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000029#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020030#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020031#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020032#endif
Paul Bakker0e04d0e2011-11-27 14:46:59 +000033
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020034#if defined(MBEDTLS_CTR_DRBG_C)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000035
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000036#include "mbedtls/ctr_drbg.h"
Paul Bakker0e04d0e2011-11-27 14:46:59 +000037
Rich Evans00ab4702015-02-06 13:43:58 +000038#include <string.h>
39
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020040#if defined(MBEDTLS_FS_IO)
Paul Bakkerfc754a92011-12-05 13:23:51 +000041#include <stdio.h>
42#endif
43
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if defined(MBEDTLS_SELF_TEST)
45#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010047#else
Rich Evans00ab4702015-02-06 13:43:58 +000048#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020049#define mbedtls_printf printf
50#endif /* MBEDTLS_PLATFORM_C */
51#endif /* MBEDTLS_SELF_TEST */
Paul Bakker7dc4c442014-02-01 22:50:26 +010052
Paul Bakkerfff03662014-06-18 16:21:25 +020053/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020054static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakkerfff03662014-06-18 16:21:25 +020055 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
56}
57
Paul Bakker18d32912011-12-10 21:42:49 +000058/*
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020059 * CTR_DRBG context initialization
60 */
61void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
62{
63 memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
64}
65
66/*
Paul Bakker18d32912011-12-10 21:42:49 +000067 * Non-public function wrapped by ctr_crbg_init(). Necessary to allow NIST
68 * tests to succeed (which require known length fixed entropy)
69 */
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020070int mbedtls_ctr_drbg_seed_entropy_len(
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020071 mbedtls_ctr_drbg_context *ctx,
Paul Bakker0e04d0e2011-11-27 14:46:59 +000072 int (*f_entropy)(void *, unsigned char *, size_t),
73 void *p_entropy,
Paul Bakker1bc9efc2011-12-03 11:29:32 +000074 const unsigned char *custom,
Paul Bakker18d32912011-12-10 21:42:49 +000075 size_t len,
76 size_t entropy_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000077{
78 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020079 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Paul Bakker0e04d0e2011-11-27 14:46:59 +000080
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020081 memset( ctx, 0, sizeof(mbedtls_ctr_drbg_context) );
82 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000083
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020084 mbedtls_aes_init( &ctx->aes_ctx );
Paul Bakkerc7ea99a2014-06-18 11:12:03 +020085
Paul Bakker0e04d0e2011-11-27 14:46:59 +000086 ctx->f_entropy = f_entropy;
87 ctx->p_entropy = p_entropy;
88
Paul Bakker18d32912011-12-10 21:42:49 +000089 ctx->entropy_len = entropy_len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020090 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
Paul Bakker0e04d0e2011-11-27 14:46:59 +000091
92 /*
93 * Initialize with an empty key
94 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020095 mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000096
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020097 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000098 return( ret );
99
100 return( 0 );
101}
102
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200103int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker18d32912011-12-10 21:42:49 +0000104 int (*f_entropy)(void *, unsigned char *, size_t),
105 void *p_entropy,
106 const unsigned char *custom,
107 size_t len )
108{
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200109 return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy, custom, len,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200110 MBEDTLS_CTR_DRBG_ENTROPY_LEN ) );
Paul Bakker18d32912011-12-10 21:42:49 +0000111}
112
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200113void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
Paul Bakkerfff03662014-06-18 16:21:25 +0200114{
115 if( ctx == NULL )
116 return;
117
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200118 mbedtls_aes_free( &ctx->aes_ctx );
119 mbedtls_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Paul Bakkerfff03662014-06-18 16:21:25 +0200120}
121
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200122void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000123{
124 ctx->prediction_resistance = resistance;
125}
126
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200127void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000128{
129 ctx->entropy_len = len;
130}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200131
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200132void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000133{
134 ctx->reseed_interval = interval;
135}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200136
137static int block_cipher_df( unsigned char *output,
138 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000139{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200140 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
141 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
142 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
143 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100144 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200145 mbedtls_aes_context aes_ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000146
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200147 int i, j;
148 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000149
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200150 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
151 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100152
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200153 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
154 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000155
156 /*
157 * Construct IV (16 bytes) and S in buffer
158 * IV = Counter (in 32-bits) padded to 16 with zeroes
159 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
160 * data || 0x80
161 * (Total is padded to a multiple of 16-bytes with zeroes)
162 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200163 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000164 *p++ = ( data_len >> 24 ) & 0xff;
165 *p++ = ( data_len >> 16 ) & 0xff;
166 *p++ = ( data_len >> 8 ) & 0xff;
167 *p++ = ( data_len ) & 0xff;
168 p += 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200169 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000170 memcpy( p, data, data_len );
171 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000172
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200173 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000174
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200175 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000176 key[i] = i;
177
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200178 mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000179
180 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200181 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000182 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200183 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000184 {
185 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200186 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000187 use_len = buf_len;
188
189 while( use_len > 0 )
190 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200191 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000192 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200193 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
194 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
195 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000196
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200197 mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000198 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200199
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200200 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000201
202 /*
203 * Update IV
204 */
205 buf[3]++;
206 }
207
208 /*
209 * Do final encryption with reduced data
210 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200211 mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS );
212 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000213 p = output;
214
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200215 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000216 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200217 mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
218 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
219 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000220 }
221
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200222 mbedtls_aes_free( &aes_ctx );
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200223
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000224 return( 0 );
225}
226
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200227static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
228 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000229{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200230 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000231 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000232 int i, j;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000233
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200234 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000235
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200236 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000237 {
238 /*
239 * Increase counter
240 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200241 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000242 if( ++ctx->counter[i - 1] != 0 )
243 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000244
245 /*
246 * Crypt counter block
247 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200248 mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000249
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200250 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000251 }
252
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200253 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000254 tmp[i] ^= data[i];
255
256 /*
257 * Update key and counter
258 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200259 mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS );
260 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000261
262 return( 0 );
263}
264
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200265void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000266 const unsigned char *additional, size_t add_len )
267{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200268 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000269
270 if( add_len > 0 )
271 {
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100272 /* MAX_INPUT would be more logical here, but we have to match
273 * block_cipher_df()'s limits since we can't propagate errors */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200274 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
275 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100276
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000277 block_cipher_df( add_input, additional, add_len );
278 ctr_drbg_update_internal( ctx, add_input );
279 }
280}
281
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200282int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000283 const unsigned char *additional, size_t len )
284{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200285 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000286 size_t seedlen = 0;
287
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200288 if( ctx->entropy_len + len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
289 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000290
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200291 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000292
293 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200294 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000295 */
296 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
297 ctx->entropy_len ) )
298 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200299 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000300 }
301
302 seedlen += ctx->entropy_len;
303
304 /*
305 * Add additional data
306 */
307 if( additional && len )
308 {
309 memcpy( seed + seedlen, additional, len );
310 seedlen += len;
311 }
312
313 /*
314 * Reduce to 384 bits
315 */
316 block_cipher_df( seed, seed, seedlen );
317
318 /*
319 * Update state
320 */
321 ctr_drbg_update_internal( ctx, seed );
322 ctx->reseed_counter = 1;
323
324 return( 0 );
325}
Paul Bakker9af723c2014-05-01 13:03:14 +0200326
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200327int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000328 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000329 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000330{
331 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200332 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
333 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000334 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200335 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000336 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000337 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000338
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200339 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
340 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000341
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200342 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
343 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000344
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200345 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000346
347 if( ctx->reseed_counter > ctx->reseed_interval ||
348 ctx->prediction_resistance )
349 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200350 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000351 return( ret );
352
353 add_len = 0;
354 }
355
356 if( add_len > 0 )
357 {
358 block_cipher_df( add_input, additional, add_len );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000359 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000360 }
361
362 while( output_len > 0 )
363 {
364 /*
365 * Increase counter
366 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200367 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000368 if( ++ctx->counter[i - 1] != 0 )
369 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000370
371 /*
372 * Crypt counter block
373 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200374 mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000375
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200376 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200377 output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000378 /*
379 * Copy random block to destination
380 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000381 memcpy( p, tmp, use_len );
382 p += use_len;
383 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000384 }
385
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000386 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000387
388 ctx->reseed_counter++;
389
390 return( 0 );
391}
392
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200393int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000394{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200395 return mbedtls_ctr_drbg_random_with_add( p_rng, output, output_len, NULL, 0 );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000396}
397
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200398#if defined(MBEDTLS_FS_IO)
399int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000400{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200401 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000402 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200403 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000404
405 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200406 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000407
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200408 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200409 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000410
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200411 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000412 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200413 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakker4c284c92014-03-26 15:33:05 +0100414 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000415 }
416
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200417 ret = 0;
418
419exit:
Paul Bakkerfc754a92011-12-05 13:23:51 +0000420 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200421 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000422}
423
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200424int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000425{
426 FILE *f;
427 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200428 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000429
430 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200431 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000432
433 fseek( f, 0, SEEK_END );
434 n = (size_t) ftell( f );
435 fseek( f, 0, SEEK_SET );
436
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200437 if( n > MBEDTLS_CTR_DRBG_MAX_INPUT )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200438 {
439 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200440 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200441 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000442
443 if( fread( buf, 1, n, f ) != n )
444 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100445 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200446 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000447 }
448
Paul Bakkerfc754a92011-12-05 13:23:51 +0000449 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200450
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200451 mbedtls_ctr_drbg_update( ctx, buf, n );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200452
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200453 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000454}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200455#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000456
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200457#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000458
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000459static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000460 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
461 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
462 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
463 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
464 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
465 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
466 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
467 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
468 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
469 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
470 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
471 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
472
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000473static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000474 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
475 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
476 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
477 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
478 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
479 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
480 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
481 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
482
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100483static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000484 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
485 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
486
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100487static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000488 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
489 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
490
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100491static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000492 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
493 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
494
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100495static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000496 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
497 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
498
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100499static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200500static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
501 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000502{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100503 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000504 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100505 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000506 return( 0 );
507}
508
Paul Bakker7dc4c442014-02-01 22:50:26 +0100509#define CHK( c ) if( (c) != 0 ) \
510 { \
511 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200512 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100513 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100514 }
515
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000516/*
517 * Checkup routine
518 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200519int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000520{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200521 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000522 unsigned char buf[16];
523
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200524 mbedtls_ctr_drbg_init( &ctx );
525
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000526 /*
527 * Based on a NIST CTR_DRBG test vector (PR = True)
528 */
529 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200530 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000531
532 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200533 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000534 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200535 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
536 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
537 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
538 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000539
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000540 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200541 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000542
543 /*
544 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
545 */
546 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200547 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000548
549 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200550 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000551 (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200552 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
553 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
554 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100555 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000556
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000557 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200558 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000559
560 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200561 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000562
563 return( 0 );
564}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200565#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000566
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200567#endif /* MBEDTLS_CTR_DRBG_C */