blob: de4a6e814c76ca7632293692e85b78e8c559ba90 [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
280 if( ctx->entropy_len + len > CTR_DRBG_MAX_SEED_INPUT )
281 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
282
283 memset( seed, 0, CTR_DRBG_MAX_SEED_INPUT );
284
285 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200286 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000287 */
288 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
289 ctx->entropy_len ) )
290 {
291 return( POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
292 }
293
294 seedlen += ctx->entropy_len;
295
296 /*
297 * Add additional data
298 */
299 if( additional && len )
300 {
301 memcpy( seed + seedlen, additional, len );
302 seedlen += len;
303 }
304
305 /*
306 * Reduce to 384 bits
307 */
308 block_cipher_df( seed, seed, seedlen );
309
310 /*
311 * Update state
312 */
313 ctr_drbg_update_internal( ctx, seed );
314 ctx->reseed_counter = 1;
315
316 return( 0 );
317}
Paul Bakker9af723c2014-05-01 13:03:14 +0200318
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000319int ctr_drbg_random_with_add( void *p_rng,
320 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000321 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000322{
323 int ret = 0;
324 ctr_drbg_context *ctx = (ctr_drbg_context *) p_rng;
325 unsigned char add_input[CTR_DRBG_SEEDLEN];
326 unsigned char *p = output;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000327 unsigned char tmp[CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000328 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000329 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000330
331 if( output_len > CTR_DRBG_MAX_REQUEST )
332 return( POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG );
333
334 if( add_len > CTR_DRBG_MAX_INPUT )
335 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
336
337 memset( add_input, 0, CTR_DRBG_SEEDLEN );
338
339 if( ctx->reseed_counter > ctx->reseed_interval ||
340 ctx->prediction_resistance )
341 {
342 if( ( ret = ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
343 return( ret );
344
345 add_len = 0;
346 }
347
348 if( add_len > 0 )
349 {
350 block_cipher_df( add_input, additional, add_len );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000351 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000352 }
353
354 while( output_len > 0 )
355 {
356 /*
357 * Increase counter
358 */
Paul Bakker369e14b2012-04-18 14:16:09 +0000359 for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
360 if( ++ctx->counter[i - 1] != 0 )
361 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000362
363 /*
364 * Crypt counter block
365 */
366 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, tmp );
367
Paul Bakker66d5d072014-06-17 16:39:18 +0200368 use_len = ( output_len > CTR_DRBG_BLOCKSIZE ) ? CTR_DRBG_BLOCKSIZE :
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200369 output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000370 /*
371 * Copy random block to destination
372 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000373 memcpy( p, tmp, use_len );
374 p += use_len;
375 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000376 }
377
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000378 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000379
380 ctx->reseed_counter++;
381
382 return( 0 );
383}
384
385int ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
386{
387 return ctr_drbg_random_with_add( p_rng, output, output_len, NULL, 0 );
388}
389
Paul Bakkerfc754a92011-12-05 13:23:51 +0000390#if defined(POLARSSL_FS_IO)
391int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path )
392{
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200393 int ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000394 FILE *f;
395 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
396
397 if( ( f = fopen( path, "wb" ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000398 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000399
400 if( ( ret = ctr_drbg_random( ctx, buf, CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200401 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000402
403 if( fwrite( buf, 1, CTR_DRBG_MAX_INPUT, f ) != CTR_DRBG_MAX_INPUT )
404 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100405 ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR;
406 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000407 }
408
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200409 ret = 0;
410
411exit:
Paul Bakkerfc754a92011-12-05 13:23:51 +0000412 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200413 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000414}
415
416int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path )
417{
418 FILE *f;
419 size_t n;
420 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
421
422 if( ( f = fopen( path, "rb" ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000423 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000424
425 fseek( f, 0, SEEK_END );
426 n = (size_t) ftell( f );
427 fseek( f, 0, SEEK_SET );
428
429 if( n > CTR_DRBG_MAX_INPUT )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200430 {
431 fclose( f );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000432 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200433 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000434
435 if( fread( buf, 1, n, f ) != n )
436 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100437 fclose( f );
438 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000439 }
440
Paul Bakkerfc754a92011-12-05 13:23:51 +0000441 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200442
443 ctr_drbg_update( ctx, buf, n );
444
Paul Bakkerfc754a92011-12-05 13:23:51 +0000445 return( ctr_drbg_write_seed_file( ctx, path ) );
446}
447#endif /* POLARSSL_FS_IO */
448
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000449#if defined(POLARSSL_SELF_TEST)
450
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100451static unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000452 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
453 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
454 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
455 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
456 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
457 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
458 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
459 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
460 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
461 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
462 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
463 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
464
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100465static unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000466 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
467 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
468 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
469 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
470 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
471 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
472 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
473 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
474
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100475static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000476 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
477 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
478
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100479static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000480 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
481 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
482
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100483static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000484 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
485 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
486
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100487static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000488 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
489 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
490
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100491static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200492static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
493 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000494{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100495 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000496 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100497 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000498 return( 0 );
499}
500
Paul Bakker7dc4c442014-02-01 22:50:26 +0100501#define CHK( c ) if( (c) != 0 ) \
502 { \
503 if( verbose != 0 ) \
504 polarssl_printf( "failed\n" ); \
505 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100506 }
507
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000508/*
509 * Checkup routine
510 */
511int ctr_drbg_self_test( int verbose )
512{
513 ctr_drbg_context ctx;
514 unsigned char buf[16];
515
516 /*
517 * Based on a NIST CTR_DRBG test vector (PR = True)
518 */
519 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100520 polarssl_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000521
522 test_offset = 0;
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100523 CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
524 entropy_source_pr, nonce_pers_pr, 16, 32 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000525 ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100526 CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) );
527 CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) );
528 CHK( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000529
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000530 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100531 polarssl_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000532
533 /*
534 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
535 */
536 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100537 polarssl_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000538
539 test_offset = 0;
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100540 CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
541 entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
542 CHK( ctr_drbg_random( &ctx, buf, 16 ) );
543 CHK( ctr_drbg_reseed( &ctx, NULL, 0 ) );
544 CHK( ctr_drbg_random( &ctx, buf, 16 ) );
545 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000546
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000547 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100548 polarssl_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000549
550 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100551 polarssl_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000552
553 return( 0 );
554}
Paul Bakker9af723c2014-05-01 13:03:14 +0200555#endif /* POLARSSL_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000556
Paul Bakker9af723c2014-05-01 13:03:14 +0200557#endif /* POLARSSL_CTR_DRBG_C */