blob: 00b50d26bca9f6bd77386c65ddc15fdac3d28f92 [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 ) );
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010064
65#if defined(MBEDTLS_THREADING_C)
66 mbedtls_mutex_init( &ctx->mutex );
67#endif
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020068}
69
70/*
Paul Bakker18d32912011-12-10 21:42:49 +000071 * Non-public function wrapped by ctr_crbg_init(). Necessary to allow NIST
72 * tests to succeed (which require known length fixed entropy)
73 */
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020074int mbedtls_ctr_drbg_seed_entropy_len(
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020075 mbedtls_ctr_drbg_context *ctx,
Paul Bakker0e04d0e2011-11-27 14:46:59 +000076 int (*f_entropy)(void *, unsigned char *, size_t),
77 void *p_entropy,
Paul Bakker1bc9efc2011-12-03 11:29:32 +000078 const unsigned char *custom,
Paul Bakker18d32912011-12-10 21:42:49 +000079 size_t len,
80 size_t entropy_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000081{
82 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020083 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Paul Bakker0e04d0e2011-11-27 14:46:59 +000084
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020085 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000086
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020087 mbedtls_aes_init( &ctx->aes_ctx );
Paul Bakkerc7ea99a2014-06-18 11:12:03 +020088
Paul Bakker0e04d0e2011-11-27 14:46:59 +000089 ctx->f_entropy = f_entropy;
90 ctx->p_entropy = p_entropy;
91
Paul Bakker18d32912011-12-10 21:42:49 +000092 ctx->entropy_len = entropy_len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020093 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
Paul Bakker0e04d0e2011-11-27 14:46:59 +000094
95 /*
96 * Initialize with an empty key
97 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020098 mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000099
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200100 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000101 return( ret );
102
103 return( 0 );
104}
105
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200106int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker18d32912011-12-10 21:42:49 +0000107 int (*f_entropy)(void *, unsigned char *, size_t),
108 void *p_entropy,
109 const unsigned char *custom,
110 size_t len )
111{
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200112 return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy, custom, len,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200113 MBEDTLS_CTR_DRBG_ENTROPY_LEN ) );
Paul Bakker18d32912011-12-10 21:42:49 +0000114}
115
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200116void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
Paul Bakkerfff03662014-06-18 16:21:25 +0200117{
118 if( ctx == NULL )
119 return;
120
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100121#if defined(MBEDTLS_THREADING_C)
122 mbedtls_mutex_free( &ctx->mutex );
123#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200124 mbedtls_aes_free( &ctx->aes_ctx );
125 mbedtls_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Paul Bakkerfff03662014-06-18 16:21:25 +0200126}
127
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200128void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000129{
130 ctx->prediction_resistance = resistance;
131}
132
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200133void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000134{
135 ctx->entropy_len = len;
136}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200137
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200138void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000139{
140 ctx->reseed_interval = interval;
141}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200142
143static int block_cipher_df( unsigned char *output,
144 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000145{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200146 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
147 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
148 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
149 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100150 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200151 mbedtls_aes_context aes_ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000152
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200153 int i, j;
154 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000155
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200156 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
157 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100158
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200159 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
160 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000161
162 /*
163 * Construct IV (16 bytes) and S in buffer
164 * IV = Counter (in 32-bits) padded to 16 with zeroes
165 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
166 * data || 0x80
167 * (Total is padded to a multiple of 16-bytes with zeroes)
168 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200169 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000170 *p++ = ( data_len >> 24 ) & 0xff;
171 *p++ = ( data_len >> 16 ) & 0xff;
172 *p++ = ( data_len >> 8 ) & 0xff;
173 *p++ = ( data_len ) & 0xff;
174 p += 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200175 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000176 memcpy( p, data, data_len );
177 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000178
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200179 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000180
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200181 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000182 key[i] = i;
183
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200184 mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000185
186 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200187 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000188 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200189 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000190 {
191 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200192 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000193 use_len = buf_len;
194
195 while( use_len > 0 )
196 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200197 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000198 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200199 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
200 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
201 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000202
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200203 mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000204 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200205
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200206 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000207
208 /*
209 * Update IV
210 */
211 buf[3]++;
212 }
213
214 /*
215 * Do final encryption with reduced data
216 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200217 mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS );
218 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000219 p = output;
220
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200221 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000222 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200223 mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
224 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
225 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000226 }
227
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200228 mbedtls_aes_free( &aes_ctx );
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200229
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000230 return( 0 );
231}
232
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200233static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
234 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000235{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200236 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000237 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000238 int i, j;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000239
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200240 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000241
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200242 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000243 {
244 /*
245 * Increase counter
246 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200247 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000248 if( ++ctx->counter[i - 1] != 0 )
249 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000250
251 /*
252 * Crypt counter block
253 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200254 mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000255
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200256 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000257 }
258
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200259 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000260 tmp[i] ^= data[i];
261
262 /*
263 * Update key and counter
264 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200265 mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS );
266 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000267
268 return( 0 );
269}
270
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200271void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000272 const unsigned char *additional, size_t add_len )
273{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200274 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000275
276 if( add_len > 0 )
277 {
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100278 /* MAX_INPUT would be more logical here, but we have to match
279 * block_cipher_df()'s limits since we can't propagate errors */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200280 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
281 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100282
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000283 block_cipher_df( add_input, additional, add_len );
284 ctr_drbg_update_internal( ctx, add_input );
285 }
286}
287
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200288int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000289 const unsigned char *additional, size_t len )
290{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200291 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000292 size_t seedlen = 0;
293
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200294 if( ctx->entropy_len + len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
295 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000296
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200297 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000298
299 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200300 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000301 */
302 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
303 ctx->entropy_len ) )
304 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200305 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000306 }
307
308 seedlen += ctx->entropy_len;
309
310 /*
311 * Add additional data
312 */
313 if( additional && len )
314 {
315 memcpy( seed + seedlen, additional, len );
316 seedlen += len;
317 }
318
319 /*
320 * Reduce to 384 bits
321 */
322 block_cipher_df( seed, seed, seedlen );
323
324 /*
325 * Update state
326 */
327 ctr_drbg_update_internal( ctx, seed );
328 ctx->reseed_counter = 1;
329
330 return( 0 );
331}
Paul Bakker9af723c2014-05-01 13:03:14 +0200332
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200333int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000334 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000335 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000336{
337 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200338 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
339 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000340 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200341 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000342 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000343 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000344
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200345 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
346 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000347
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200348 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
349 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000350
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200351 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000352
353 if( ctx->reseed_counter > ctx->reseed_interval ||
354 ctx->prediction_resistance )
355 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200356 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000357 return( ret );
358
359 add_len = 0;
360 }
361
362 if( add_len > 0 )
363 {
364 block_cipher_df( add_input, additional, add_len );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000365 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000366 }
367
368 while( output_len > 0 )
369 {
370 /*
371 * Increase counter
372 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200373 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000374 if( ++ctx->counter[i - 1] != 0 )
375 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000376
377 /*
378 * Crypt counter block
379 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200380 mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000381
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200382 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200383 output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000384 /*
385 * Copy random block to destination
386 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000387 memcpy( p, tmp, use_len );
388 p += use_len;
389 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000390 }
391
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000392 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000393
394 ctx->reseed_counter++;
395
396 return( 0 );
397}
398
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200399int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000400{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100401 int ret;
402 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
403
404#if defined(MBEDTLS_THREADING_C)
405 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
406 return( ret );
407#endif
408
409 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
410
411#if defined(MBEDTLS_THREADING_C)
412 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
413 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
414#endif
415
416 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000417}
418
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200419#if defined(MBEDTLS_FS_IO)
420int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000421{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200422 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000423 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200424 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000425
426 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200427 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000428
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200429 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200430 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000431
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200432 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000433 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200434 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakker4c284c92014-03-26 15:33:05 +0100435 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000436 }
437
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200438 ret = 0;
439
440exit:
Paul Bakkerfc754a92011-12-05 13:23:51 +0000441 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200442 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000443}
444
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200445int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000446{
447 FILE *f;
448 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000450
451 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200452 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000453
454 fseek( f, 0, SEEK_END );
455 n = (size_t) ftell( f );
456 fseek( f, 0, SEEK_SET );
457
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200458 if( n > MBEDTLS_CTR_DRBG_MAX_INPUT )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200459 {
460 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200461 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200462 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000463
464 if( fread( buf, 1, n, f ) != n )
465 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100466 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200467 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000468 }
469
Paul Bakkerfc754a92011-12-05 13:23:51 +0000470 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200471
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200472 mbedtls_ctr_drbg_update( ctx, buf, n );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200473
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200474 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000475}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200476#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000477
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200478#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000479
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000480static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000481 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
482 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
483 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
484 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
485 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
486 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
487 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
488 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
489 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
490 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
491 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
492 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
493
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000494static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000495 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
496 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
497 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
498 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
499 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
500 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
501 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
502 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
503
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100504static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000505 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
506 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
507
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100508static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000509 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
510 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
511
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100512static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000513 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
514 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
515
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100516static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000517 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
518 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
519
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100520static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200521static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
522 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000523{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100524 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000525 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100526 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000527 return( 0 );
528}
529
Paul Bakker7dc4c442014-02-01 22:50:26 +0100530#define CHK( c ) if( (c) != 0 ) \
531 { \
532 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200533 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100534 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100535 }
536
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000537/*
538 * Checkup routine
539 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200540int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000541{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200542 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000543 unsigned char buf[16];
544
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200545 mbedtls_ctr_drbg_init( &ctx );
546
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000547 /*
548 * Based on a NIST CTR_DRBG test vector (PR = True)
549 */
550 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200551 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000552
553 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200554 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000555 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200556 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
557 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
558 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
559 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000560
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100561 mbedtls_ctr_drbg_free( &ctx );
562
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000563 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200564 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000565
566 /*
567 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
568 */
569 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200570 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000571
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100572 mbedtls_ctr_drbg_init( &ctx );
573
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000574 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200575 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000576 (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200577 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
578 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
579 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100580 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000581
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100582 mbedtls_ctr_drbg_free( &ctx );
583
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000584 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200585 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000586
587 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200588 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000589
590 return( 0 );
591}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200592#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000593
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200594#endif /* MBEDTLS_CTR_DRBG_C */