blob: 7b315e888bc238c74b73cc02bd5658cd3efe1d19 [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é-Gonnardcef4ad22014-04-29 12:39:06 +020028#if !defined(POLARSSL_CONFIG_FILE)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000029#include "polarssl/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020030#else
31#include POLARSSL_CONFIG_FILE
32#endif
Paul Bakker0e04d0e2011-11-27 14:46:59 +000033
34#if defined(POLARSSL_CTR_DRBG_C)
35
36#include "polarssl/ctr_drbg.h"
37
Rich Evans00ab4702015-02-06 13:43:58 +000038#include <string.h>
39
Paul Bakkerfc754a92011-12-05 13:23:51 +000040#if defined(POLARSSL_FS_IO)
41#include <stdio.h>
42#endif
43
Rich Evans00ab4702015-02-06 13:43:58 +000044#if defined(POLARSSL_SELF_TEST)
Paul Bakker7dc4c442014-02-01 22:50:26 +010045#if defined(POLARSSL_PLATFORM_C)
46#include "polarssl/platform.h"
47#else
Rich Evans00ab4702015-02-06 13:43:58 +000048#include <stdio.h>
Paul Bakker7dc4c442014-02-01 22:50:26 +010049#define polarssl_printf printf
Rich Evans00ab4702015-02-06 13:43:58 +000050#endif /* POLARSSL_PLATFORM_C */
51#endif /* POLARSSL_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 */
54static void polarssl_zeroize( void *v, size_t n ) {
55 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
56}
57
Paul Bakker18d32912011-12-10 21:42:49 +000058/*
59 * Non-public function wrapped by ctr_crbg_init(). Necessary to allow NIST
60 * tests to succeed (which require known length fixed entropy)
61 */
Paul Bakker534f82c2013-06-25 16:47:55 +020062int ctr_drbg_init_entropy_len(
Paul Bakker18d32912011-12-10 21:42:49 +000063 ctr_drbg_context *ctx,
Paul Bakker0e04d0e2011-11-27 14:46:59 +000064 int (*f_entropy)(void *, unsigned char *, size_t),
65 void *p_entropy,
Paul Bakker1bc9efc2011-12-03 11:29:32 +000066 const unsigned char *custom,
Paul Bakker18d32912011-12-10 21:42:49 +000067 size_t len,
68 size_t entropy_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000069{
70 int ret;
Paul Bakker2bc7cf12011-11-29 10:50:51 +000071 unsigned char key[CTR_DRBG_KEYSIZE];
Paul Bakker0e04d0e2011-11-27 14:46:59 +000072
73 memset( ctx, 0, sizeof(ctr_drbg_context) );
Paul Bakker2bc7cf12011-11-29 10:50:51 +000074 memset( key, 0, CTR_DRBG_KEYSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000075
Paul Bakkerc7ea99a2014-06-18 11:12:03 +020076 aes_init( &ctx->aes_ctx );
77
Paul Bakker0e04d0e2011-11-27 14:46:59 +000078 ctx->f_entropy = f_entropy;
79 ctx->p_entropy = p_entropy;
80
Paul Bakker18d32912011-12-10 21:42:49 +000081 ctx->entropy_len = entropy_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +000082 ctx->reseed_interval = CTR_DRBG_RESEED_INTERVAL;
83
84 /*
85 * Initialize with an empty key
86 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +000087 aes_setkey_enc( &ctx->aes_ctx, key, CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000088
89 if( ( ret = ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
90 return( ret );
91
92 return( 0 );
93}
94
Paul Bakker18d32912011-12-10 21:42:49 +000095int ctr_drbg_init( ctr_drbg_context *ctx,
96 int (*f_entropy)(void *, unsigned char *, size_t),
97 void *p_entropy,
98 const unsigned char *custom,
99 size_t len )
100{
101 return( ctr_drbg_init_entropy_len( ctx, f_entropy, p_entropy, custom, len,
102 CTR_DRBG_ENTROPY_LEN ) );
103}
104
Paul Bakkerfff03662014-06-18 16:21:25 +0200105void ctr_drbg_free( ctr_drbg_context *ctx )
106{
107 if( ctx == NULL )
108 return;
109
110 aes_free( &ctx->aes_ctx );
111 polarssl_zeroize( ctx, sizeof( ctr_drbg_context ) );
112}
113
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000114void ctr_drbg_set_prediction_resistance( ctr_drbg_context *ctx, int resistance )
115{
116 ctx->prediction_resistance = resistance;
117}
118
119void ctr_drbg_set_entropy_len( ctr_drbg_context *ctx, size_t len )
120{
121 ctx->entropy_len = len;
122}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200123
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000124void ctr_drbg_set_reseed_interval( ctr_drbg_context *ctx, int interval )
125{
126 ctx->reseed_interval = interval;
127}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200128
129static int block_cipher_df( unsigned char *output,
130 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000131{
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000132 unsigned char buf[CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000133 unsigned char tmp[CTR_DRBG_SEEDLEN];
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000134 unsigned char key[CTR_DRBG_KEYSIZE];
135 unsigned char chain[CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100136 unsigned char *p, *iv;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000137 aes_context aes_ctx;
138
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200139 int i, j;
140 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000141
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100142 if( data_len > CTR_DRBG_MAX_SEED_INPUT )
143 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
144
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000145 memset( buf, 0, CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16 );
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200146 aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000147
148 /*
149 * Construct IV (16 bytes) and S in buffer
150 * IV = Counter (in 32-bits) padded to 16 with zeroes
151 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
152 * data || 0x80
153 * (Total is padded to a multiple of 16-bytes with zeroes)
154 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000155 p = buf + CTR_DRBG_BLOCKSIZE;
156 *p++ = ( data_len >> 24 ) & 0xff;
157 *p++ = ( data_len >> 16 ) & 0xff;
158 *p++ = ( data_len >> 8 ) & 0xff;
159 *p++ = ( data_len ) & 0xff;
160 p += 3;
161 *p++ = CTR_DRBG_SEEDLEN;
162 memcpy( p, data, data_len );
163 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000164
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000165 buf_len = CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000166
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000167 for( i = 0; i < CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000168 key[i] = i;
169
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000170 aes_setkey_enc( &aes_ctx, key, CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000171
172 /*
173 * Reduce data to POLARSSL_CTR_DRBG_SEEDLEN bytes of data
174 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000175 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000176 {
177 p = buf;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000178 memset( chain, 0, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000179 use_len = buf_len;
180
181 while( use_len > 0 )
182 {
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000183 for( i = 0; i < CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000184 chain[i] ^= p[i];
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000185 p += CTR_DRBG_BLOCKSIZE;
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200186 use_len -= ( use_len >= CTR_DRBG_BLOCKSIZE ) ?
187 CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000188
189 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, chain, chain );
190 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200191
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000192 memcpy( tmp + j, chain, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000193
194 /*
195 * Update IV
196 */
197 buf[3]++;
198 }
199
200 /*
201 * Do final encryption with reduced data
202 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000203 aes_setkey_enc( &aes_ctx, tmp, CTR_DRBG_KEYBITS );
204 iv = tmp + CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000205 p = output;
206
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000207 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000208 {
209 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, iv, iv );
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000210 memcpy( p, iv, CTR_DRBG_BLOCKSIZE );
211 p += CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000212 }
213
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200214 aes_free( &aes_ctx );
215
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000216 return( 0 );
217}
218
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200219static int ctr_drbg_update_internal( ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000220 const unsigned char data[CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000221{
222 unsigned char tmp[CTR_DRBG_SEEDLEN];
223 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000224 int i, j;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000225
226 memset( tmp, 0, CTR_DRBG_SEEDLEN );
227
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000228 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000229 {
230 /*
231 * Increase counter
232 */
Paul Bakker9a736322012-11-14 12:39:52 +0000233 for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000234 if( ++ctx->counter[i - 1] != 0 )
235 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000236
237 /*
238 * Crypt counter block
239 */
240 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, p );
241
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000242 p += CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000243 }
244
245 for( i = 0; i < CTR_DRBG_SEEDLEN; i++ )
246 tmp[i] ^= data[i];
247
248 /*
249 * Update key and counter
250 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000251 aes_setkey_enc( &ctx->aes_ctx, tmp, CTR_DRBG_KEYBITS );
252 memcpy( ctx->counter, tmp + CTR_DRBG_KEYSIZE, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000253
254 return( 0 );
255}
256
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000257void ctr_drbg_update( ctr_drbg_context *ctx,
258 const unsigned char *additional, size_t add_len )
259{
260 unsigned char add_input[CTR_DRBG_SEEDLEN];
261
262 if( add_len > 0 )
263 {
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100264 /* MAX_INPUT would be more logical here, but we have to match
265 * block_cipher_df()'s limits since we can't propagate errors */
266 if( add_len > CTR_DRBG_MAX_SEED_INPUT )
267 add_len = CTR_DRBG_MAX_SEED_INPUT;
268
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000269 block_cipher_df( add_input, additional, add_len );
270 ctr_drbg_update_internal( ctx, add_input );
271 }
272}
273
274int ctr_drbg_reseed( ctr_drbg_context *ctx,
275 const unsigned char *additional, size_t len )
276{
277 unsigned char seed[CTR_DRBG_MAX_SEED_INPUT];
278 size_t seedlen = 0;
279
Andres Amaya Garcia74ef6502017-01-18 13:56:58 +0000280 if( ctx->entropy_len > CTR_DRBG_MAX_SEED_INPUT ||
281 len > CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000282 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
283
284 memset( seed, 0, CTR_DRBG_MAX_SEED_INPUT );
285
286 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200287 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000288 */
289 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
290 ctx->entropy_len ) )
291 {
292 return( POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
293 }
294
295 seedlen += ctx->entropy_len;
296
297 /*
298 * Add additional data
299 */
300 if( additional && len )
301 {
302 memcpy( seed + seedlen, additional, len );
303 seedlen += len;
304 }
305
306 /*
307 * Reduce to 384 bits
308 */
309 block_cipher_df( seed, seed, seedlen );
310
311 /*
312 * Update state
313 */
314 ctr_drbg_update_internal( ctx, seed );
315 ctx->reseed_counter = 1;
316
317 return( 0 );
318}
Paul Bakker9af723c2014-05-01 13:03:14 +0200319
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000320int ctr_drbg_random_with_add( void *p_rng,
321 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000322 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000323{
324 int ret = 0;
325 ctr_drbg_context *ctx = (ctr_drbg_context *) p_rng;
326 unsigned char add_input[CTR_DRBG_SEEDLEN];
327 unsigned char *p = output;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000328 unsigned char tmp[CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000329 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000330 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000331
332 if( output_len > CTR_DRBG_MAX_REQUEST )
333 return( POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG );
334
335 if( add_len > CTR_DRBG_MAX_INPUT )
336 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
337
338 memset( add_input, 0, CTR_DRBG_SEEDLEN );
339
340 if( ctx->reseed_counter > ctx->reseed_interval ||
341 ctx->prediction_resistance )
342 {
343 if( ( ret = ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
344 return( ret );
345
346 add_len = 0;
347 }
348
349 if( add_len > 0 )
350 {
351 block_cipher_df( add_input, additional, add_len );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000352 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000353 }
354
355 while( output_len > 0 )
356 {
357 /*
358 * Increase counter
359 */
Paul Bakker369e14b2012-04-18 14:16:09 +0000360 for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
361 if( ++ctx->counter[i - 1] != 0 )
362 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000363
364 /*
365 * Crypt counter block
366 */
367 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, tmp );
368
Paul Bakker66d5d072014-06-17 16:39:18 +0200369 use_len = ( output_len > CTR_DRBG_BLOCKSIZE ) ? CTR_DRBG_BLOCKSIZE :
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200370 output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000371 /*
372 * Copy random block to destination
373 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000374 memcpy( p, tmp, use_len );
375 p += use_len;
376 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000377 }
378
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000379 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000380
381 ctx->reseed_counter++;
382
383 return( 0 );
384}
385
386int ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
387{
388 return ctr_drbg_random_with_add( p_rng, output, output_len, NULL, 0 );
389}
390
Paul Bakkerfc754a92011-12-05 13:23:51 +0000391#if defined(POLARSSL_FS_IO)
392int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path )
393{
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200394 int ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000395 FILE *f;
396 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
397
398 if( ( f = fopen( path, "wb" ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000399 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000400
401 if( ( ret = ctr_drbg_random( ctx, buf, CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200402 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000403
404 if( fwrite( buf, 1, CTR_DRBG_MAX_INPUT, f ) != CTR_DRBG_MAX_INPUT )
405 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100406 ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR;
407 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000408 }
409
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200410 ret = 0;
411
412exit:
Paul Bakkerfc754a92011-12-05 13:23:51 +0000413 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200414 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000415}
416
417int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path )
418{
419 FILE *f;
420 size_t n;
421 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
422
423 if( ( f = fopen( path, "rb" ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000424 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000425
426 fseek( f, 0, SEEK_END );
427 n = (size_t) ftell( f );
428 fseek( f, 0, SEEK_SET );
429
430 if( n > CTR_DRBG_MAX_INPUT )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200431 {
432 fclose( f );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000433 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200434 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000435
436 if( fread( buf, 1, n, f ) != n )
437 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100438 fclose( f );
439 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000440 }
441
Paul Bakkerfc754a92011-12-05 13:23:51 +0000442 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200443
444 ctr_drbg_update( ctx, buf, n );
445
Paul Bakkerfc754a92011-12-05 13:23:51 +0000446 return( ctr_drbg_write_seed_file( ctx, path ) );
447}
448#endif /* POLARSSL_FS_IO */
449
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000450#if defined(POLARSSL_SELF_TEST)
451
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000452static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000453 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
454 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
455 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
456 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
457 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
458 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
459 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
460 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
461 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
462 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
463 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
464 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
465
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000466static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000467 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
468 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
469 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
470 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
471 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
472 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
473 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
474 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
475
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100476static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000477 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
478 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
479
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100480static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000481 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
482 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
483
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100484static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000485 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
486 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
487
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100488static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000489 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
490 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
491
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100492static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200493static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
494 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000495{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100496 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000497 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100498 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000499 return( 0 );
500}
501
Paul Bakker7dc4c442014-02-01 22:50:26 +0100502#define CHK( c ) if( (c) != 0 ) \
503 { \
504 if( verbose != 0 ) \
505 polarssl_printf( "failed\n" ); \
506 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100507 }
508
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000509/*
510 * Checkup routine
511 */
512int ctr_drbg_self_test( int verbose )
513{
514 ctr_drbg_context ctx;
515 unsigned char buf[16];
516
517 /*
518 * Based on a NIST CTR_DRBG test vector (PR = True)
519 */
520 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100521 polarssl_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000522
523 test_offset = 0;
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100524 CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000525 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000526 ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100527 CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) );
528 CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) );
529 CHK( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000530
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000531 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100532 polarssl_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000533
534 /*
535 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
536 */
537 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100538 polarssl_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000539
540 test_offset = 0;
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100541 CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000542 (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100543 CHK( ctr_drbg_random( &ctx, buf, 16 ) );
544 CHK( ctr_drbg_reseed( &ctx, NULL, 0 ) );
545 CHK( ctr_drbg_random( &ctx, buf, 16 ) );
546 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000547
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000548 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100549 polarssl_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000550
551 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100552 polarssl_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000553
554 return( 0 );
555}
Paul Bakker9af723c2014-05-01 13:03:14 +0200556#endif /* POLARSSL_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000557
Paul Bakker9af723c2014-05-01 13:03:14 +0200558#endif /* POLARSSL_CTR_DRBG_C */