blob: f66064ff4f5affedeb3eb6bd9a240c820cf68cc2 [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 Garciac0dc5b52017-07-12 10:56:39 +0100409exit:
Andres Amaya Garciadd471782017-07-12 10:43:11 +0100410 polarssl_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200411
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 Garciac0dc5b52017-07-12 10:56:39 +0100431 {
432 fclose( f );
433 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
434 }
435
436 if( fread( buf, 1, n, f ) != n )
Andres Amaya Garciadd471782017-07-12 10:43:11 +0100437 ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR;
438 else
439 ctr_drbg_update( ctx, buf, n );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000440
Paul Bakkerfc754a92011-12-05 13:23:51 +0000441 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200442
Andres Amaya Garciadd471782017-07-12 10:43:11 +0100443 polarssl_zeroize( buf, sizeof( buf ) );
444
445 if( ret != 0 )
446 return( ret );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200447
Paul Bakkerfc754a92011-12-05 13:23:51 +0000448 return( ctr_drbg_write_seed_file( ctx, path ) );
449}
450#endif /* POLARSSL_FS_IO */
451
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000452#if defined(POLARSSL_SELF_TEST)
453
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000454static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000455 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
456 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
457 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
458 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
459 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
460 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
461 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
462 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
463 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
464 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
465 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
466 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
467
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000468static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000469 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
470 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
471 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
472 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
473 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
474 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
475 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
476 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
477
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100478static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000479 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
480 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
481
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100482static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000483 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
484 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
485
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100486static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000487 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
488 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
489
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100490static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000491 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
492 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
493
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100494static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200495static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
496 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000497{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100498 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000499 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100500 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000501 return( 0 );
502}
503
Paul Bakker7dc4c442014-02-01 22:50:26 +0100504#define CHK( c ) if( (c) != 0 ) \
505 { \
506 if( verbose != 0 ) \
507 polarssl_printf( "failed\n" ); \
508 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100509 }
510
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000511/*
512 * Checkup routine
513 */
514int ctr_drbg_self_test( int verbose )
515{
516 ctr_drbg_context ctx;
517 unsigned char buf[16];
518
519 /*
520 * Based on a NIST CTR_DRBG test vector (PR = True)
521 */
522 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100523 polarssl_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000524
525 test_offset = 0;
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100526 CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000527 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000528 ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100529 CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) );
530 CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) );
531 CHK( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000532
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000533 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100534 polarssl_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000535
536 /*
537 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
538 */
539 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100540 polarssl_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000541
542 test_offset = 0;
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100543 CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000544 (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100545 CHK( ctr_drbg_random( &ctx, buf, 16 ) );
546 CHK( ctr_drbg_reseed( &ctx, NULL, 0 ) );
547 CHK( ctr_drbg_random( &ctx, buf, 16 ) );
548 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000549
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000550 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100551 polarssl_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000552
553 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100554 polarssl_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000555
556 return( 0 );
557}
Paul Bakker9af723c2014-05-01 13:03:14 +0200558#endif /* POLARSSL_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000559
Paul Bakker9af723c2014-05-01 13:03:14 +0200560#endif /* POLARSSL_CTR_DRBG_C */