blob: fe7fb27ae7eb9a28c8241acbf7f130d4a8ae8f4e [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 )
Paul Bakker4c284c92014-03-26 15:33:05 +0100405 ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR;
Andres Amaya Garciadd471782017-07-12 10:43:11 +0100406 else
407 ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000408
Andres Amaya Garciadd471782017-07-12 10:43:11 +0100409 polarssl_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200410
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{
Andres Amaya Garciadd471782017-07-12 10:43:11 +0100418 int ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000419 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 )
Andres Amaya Garciadd471782017-07-12 10:43:11 +0100431 ret = POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG;
432 else if( fread( buf, 1, n, f ) != n )
433 ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR;
434 else
435 ctr_drbg_update( ctx, buf, n );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000436
Paul Bakkerfc754a92011-12-05 13:23:51 +0000437 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200438
Andres Amaya Garciadd471782017-07-12 10:43:11 +0100439 polarssl_zeroize( buf, sizeof( buf ) );
440
441 if( ret != 0 )
442 return( ret );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200443
Paul Bakkerfc754a92011-12-05 13:23:51 +0000444 return( ctr_drbg_write_seed_file( ctx, path ) );
445}
446#endif /* POLARSSL_FS_IO */
447
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000448#if defined(POLARSSL_SELF_TEST)
449
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000450static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000451 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
452 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
453 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
454 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
455 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
456 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
457 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
458 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
459 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
460 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
461 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
462 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
463
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000464static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000465 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
466 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
467 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
468 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
469 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
470 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
471 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
472 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
473
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100474static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000475 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
476 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
477
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100478static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000479 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
480 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
481
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100482static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000483 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
484 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
485
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100486static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000487 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
488 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
489
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100490static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200491static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
492 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000493{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100494 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000495 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100496 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000497 return( 0 );
498}
499
Paul Bakker7dc4c442014-02-01 22:50:26 +0100500#define CHK( c ) if( (c) != 0 ) \
501 { \
502 if( verbose != 0 ) \
503 polarssl_printf( "failed\n" ); \
504 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100505 }
506
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000507/*
508 * Checkup routine
509 */
510int ctr_drbg_self_test( int verbose )
511{
512 ctr_drbg_context ctx;
513 unsigned char buf[16];
514
515 /*
516 * Based on a NIST CTR_DRBG test vector (PR = True)
517 */
518 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100519 polarssl_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000520
521 test_offset = 0;
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100522 CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000523 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000524 ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100525 CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) );
526 CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) );
527 CHK( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000528
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000529 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100530 polarssl_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000531
532 /*
533 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
534 */
535 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100536 polarssl_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000537
538 test_offset = 0;
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100539 CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000540 (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100541 CHK( ctr_drbg_random( &ctx, buf, 16 ) );
542 CHK( ctr_drbg_reseed( &ctx, NULL, 0 ) );
543 CHK( ctr_drbg_random( &ctx, buf, 16 ) );
544 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000545
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000546 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100547 polarssl_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000548
549 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100550 polarssl_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000551
552 return( 0 );
553}
Paul Bakker9af723c2014-05-01 13:03:14 +0200554#endif /* POLARSSL_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000555
Paul Bakker9af723c2014-05-01 13:03:14 +0200556#endif /* POLARSSL_CTR_DRBG_C */