blob: 5e6384809c5dc456d65431718f179c0ebfb0d82e [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é-Gonnard860b5162015-01-28 17:12:07 +00006 * This file is part of mbed TLS (https://polarssl.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
Paul Bakkerfc754a92011-12-05 13:23:51 +000038#if defined(POLARSSL_FS_IO)
39#include <stdio.h>
40#endif
41
Paul Bakker7dc4c442014-02-01 22:50:26 +010042#if defined(POLARSSL_PLATFORM_C)
43#include "polarssl/platform.h"
44#else
45#define polarssl_printf printf
46#endif
47
Paul Bakkerfff03662014-06-18 16:21:25 +020048/* Implementation that should never be optimized out by the compiler */
49static void polarssl_zeroize( void *v, size_t n ) {
50 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
51}
52
Paul Bakker18d32912011-12-10 21:42:49 +000053/*
54 * Non-public function wrapped by ctr_crbg_init(). Necessary to allow NIST
55 * tests to succeed (which require known length fixed entropy)
56 */
Paul Bakker534f82c2013-06-25 16:47:55 +020057int ctr_drbg_init_entropy_len(
Paul Bakker18d32912011-12-10 21:42:49 +000058 ctr_drbg_context *ctx,
Paul Bakker0e04d0e2011-11-27 14:46:59 +000059 int (*f_entropy)(void *, unsigned char *, size_t),
60 void *p_entropy,
Paul Bakker1bc9efc2011-12-03 11:29:32 +000061 const unsigned char *custom,
Paul Bakker18d32912011-12-10 21:42:49 +000062 size_t len,
63 size_t entropy_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000064{
65 int ret;
Paul Bakker2bc7cf12011-11-29 10:50:51 +000066 unsigned char key[CTR_DRBG_KEYSIZE];
Paul Bakker0e04d0e2011-11-27 14:46:59 +000067
68 memset( ctx, 0, sizeof(ctr_drbg_context) );
Paul Bakker2bc7cf12011-11-29 10:50:51 +000069 memset( key, 0, CTR_DRBG_KEYSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000070
Paul Bakkerc7ea99a2014-06-18 11:12:03 +020071 aes_init( &ctx->aes_ctx );
72
Paul Bakker0e04d0e2011-11-27 14:46:59 +000073 ctx->f_entropy = f_entropy;
74 ctx->p_entropy = p_entropy;
75
Paul Bakker18d32912011-12-10 21:42:49 +000076 ctx->entropy_len = entropy_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +000077 ctx->reseed_interval = CTR_DRBG_RESEED_INTERVAL;
78
79 /*
80 * Initialize with an empty key
81 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +000082 aes_setkey_enc( &ctx->aes_ctx, key, CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000083
84 if( ( ret = ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
85 return( ret );
86
87 return( 0 );
88}
89
Paul Bakker18d32912011-12-10 21:42:49 +000090int ctr_drbg_init( ctr_drbg_context *ctx,
91 int (*f_entropy)(void *, unsigned char *, size_t),
92 void *p_entropy,
93 const unsigned char *custom,
94 size_t len )
95{
96 return( ctr_drbg_init_entropy_len( ctx, f_entropy, p_entropy, custom, len,
97 CTR_DRBG_ENTROPY_LEN ) );
98}
99
Paul Bakkerfff03662014-06-18 16:21:25 +0200100void ctr_drbg_free( ctr_drbg_context *ctx )
101{
102 if( ctx == NULL )
103 return;
104
105 aes_free( &ctx->aes_ctx );
106 polarssl_zeroize( ctx, sizeof( ctr_drbg_context ) );
107}
108
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000109void ctr_drbg_set_prediction_resistance( ctr_drbg_context *ctx, int resistance )
110{
111 ctx->prediction_resistance = resistance;
112}
113
114void ctr_drbg_set_entropy_len( ctr_drbg_context *ctx, size_t len )
115{
116 ctx->entropy_len = len;
117}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200118
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000119void ctr_drbg_set_reseed_interval( ctr_drbg_context *ctx, int interval )
120{
121 ctx->reseed_interval = interval;
122}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200123
124static int block_cipher_df( unsigned char *output,
125 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000126{
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000127 unsigned char buf[CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000128 unsigned char tmp[CTR_DRBG_SEEDLEN];
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000129 unsigned char key[CTR_DRBG_KEYSIZE];
130 unsigned char chain[CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100131 unsigned char *p, *iv;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000132 aes_context aes_ctx;
133
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200134 int i, j;
135 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000136
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100137 if( data_len > CTR_DRBG_MAX_SEED_INPUT )
138 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
139
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000140 memset( buf, 0, CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16 );
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200141 aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000142
143 /*
144 * Construct IV (16 bytes) and S in buffer
145 * IV = Counter (in 32-bits) padded to 16 with zeroes
146 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
147 * data || 0x80
148 * (Total is padded to a multiple of 16-bytes with zeroes)
149 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000150 p = buf + CTR_DRBG_BLOCKSIZE;
151 *p++ = ( data_len >> 24 ) & 0xff;
152 *p++ = ( data_len >> 16 ) & 0xff;
153 *p++ = ( data_len >> 8 ) & 0xff;
154 *p++ = ( data_len ) & 0xff;
155 p += 3;
156 *p++ = CTR_DRBG_SEEDLEN;
157 memcpy( p, data, data_len );
158 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000159
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000160 buf_len = CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000161
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000162 for( i = 0; i < CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000163 key[i] = i;
164
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000165 aes_setkey_enc( &aes_ctx, key, CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000166
167 /*
168 * Reduce data to POLARSSL_CTR_DRBG_SEEDLEN bytes of data
169 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000170 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000171 {
172 p = buf;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000173 memset( chain, 0, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000174 use_len = buf_len;
175
176 while( use_len > 0 )
177 {
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000178 for( i = 0; i < CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000179 chain[i] ^= p[i];
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000180 p += CTR_DRBG_BLOCKSIZE;
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200181 use_len -= ( use_len >= CTR_DRBG_BLOCKSIZE ) ?
182 CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000183
184 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, chain, chain );
185 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200186
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000187 memcpy( tmp + j, chain, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000188
189 /*
190 * Update IV
191 */
192 buf[3]++;
193 }
194
195 /*
196 * Do final encryption with reduced data
197 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000198 aes_setkey_enc( &aes_ctx, tmp, CTR_DRBG_KEYBITS );
199 iv = tmp + CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000200 p = output;
201
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000202 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000203 {
204 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, iv, iv );
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000205 memcpy( p, iv, CTR_DRBG_BLOCKSIZE );
206 p += CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000207 }
208
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200209 aes_free( &aes_ctx );
210
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000211 return( 0 );
212}
213
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200214static int ctr_drbg_update_internal( ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000215 const unsigned char data[CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000216{
217 unsigned char tmp[CTR_DRBG_SEEDLEN];
218 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000219 int i, j;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000220
221 memset( tmp, 0, CTR_DRBG_SEEDLEN );
222
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000223 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000224 {
225 /*
226 * Increase counter
227 */
Paul Bakker9a736322012-11-14 12:39:52 +0000228 for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000229 if( ++ctx->counter[i - 1] != 0 )
230 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000231
232 /*
233 * Crypt counter block
234 */
235 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, p );
236
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000237 p += CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000238 }
239
240 for( i = 0; i < CTR_DRBG_SEEDLEN; i++ )
241 tmp[i] ^= data[i];
242
243 /*
244 * Update key and counter
245 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000246 aes_setkey_enc( &ctx->aes_ctx, tmp, CTR_DRBG_KEYBITS );
247 memcpy( ctx->counter, tmp + CTR_DRBG_KEYSIZE, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000248
249 return( 0 );
250}
251
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000252void ctr_drbg_update( ctr_drbg_context *ctx,
253 const unsigned char *additional, size_t add_len )
254{
255 unsigned char add_input[CTR_DRBG_SEEDLEN];
256
257 if( add_len > 0 )
258 {
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100259 /* MAX_INPUT would be more logical here, but we have to match
260 * block_cipher_df()'s limits since we can't propagate errors */
261 if( add_len > CTR_DRBG_MAX_SEED_INPUT )
262 add_len = CTR_DRBG_MAX_SEED_INPUT;
263
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000264 block_cipher_df( add_input, additional, add_len );
265 ctr_drbg_update_internal( ctx, add_input );
266 }
267}
268
269int ctr_drbg_reseed( ctr_drbg_context *ctx,
270 const unsigned char *additional, size_t len )
271{
272 unsigned char seed[CTR_DRBG_MAX_SEED_INPUT];
273 size_t seedlen = 0;
274
275 if( ctx->entropy_len + len > CTR_DRBG_MAX_SEED_INPUT )
276 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
277
278 memset( seed, 0, CTR_DRBG_MAX_SEED_INPUT );
279
280 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200281 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000282 */
283 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
284 ctx->entropy_len ) )
285 {
286 return( POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
287 }
288
289 seedlen += ctx->entropy_len;
290
291 /*
292 * Add additional data
293 */
294 if( additional && len )
295 {
296 memcpy( seed + seedlen, additional, len );
297 seedlen += len;
298 }
299
300 /*
301 * Reduce to 384 bits
302 */
303 block_cipher_df( seed, seed, seedlen );
304
305 /*
306 * Update state
307 */
308 ctr_drbg_update_internal( ctx, seed );
309 ctx->reseed_counter = 1;
310
311 return( 0 );
312}
Paul Bakker9af723c2014-05-01 13:03:14 +0200313
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000314int ctr_drbg_random_with_add( void *p_rng,
315 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000316 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000317{
318 int ret = 0;
319 ctr_drbg_context *ctx = (ctr_drbg_context *) p_rng;
320 unsigned char add_input[CTR_DRBG_SEEDLEN];
321 unsigned char *p = output;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000322 unsigned char tmp[CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000323 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000324 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000325
326 if( output_len > CTR_DRBG_MAX_REQUEST )
327 return( POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG );
328
329 if( add_len > CTR_DRBG_MAX_INPUT )
330 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
331
332 memset( add_input, 0, CTR_DRBG_SEEDLEN );
333
334 if( ctx->reseed_counter > ctx->reseed_interval ||
335 ctx->prediction_resistance )
336 {
337 if( ( ret = ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
338 return( ret );
339
340 add_len = 0;
341 }
342
343 if( add_len > 0 )
344 {
345 block_cipher_df( add_input, additional, add_len );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000346 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000347 }
348
349 while( output_len > 0 )
350 {
351 /*
352 * Increase counter
353 */
Paul Bakker369e14b2012-04-18 14:16:09 +0000354 for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
355 if( ++ctx->counter[i - 1] != 0 )
356 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000357
358 /*
359 * Crypt counter block
360 */
361 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, tmp );
362
Paul Bakker66d5d072014-06-17 16:39:18 +0200363 use_len = ( output_len > CTR_DRBG_BLOCKSIZE ) ? CTR_DRBG_BLOCKSIZE :
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200364 output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000365 /*
366 * Copy random block to destination
367 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000368 memcpy( p, tmp, use_len );
369 p += use_len;
370 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000371 }
372
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000373 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000374
375 ctx->reseed_counter++;
376
377 return( 0 );
378}
379
380int ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
381{
382 return ctr_drbg_random_with_add( p_rng, output, output_len, NULL, 0 );
383}
384
Paul Bakkerfc754a92011-12-05 13:23:51 +0000385#if defined(POLARSSL_FS_IO)
386int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path )
387{
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200388 int ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000389 FILE *f;
390 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
391
392 if( ( f = fopen( path, "wb" ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000393 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000394
395 if( ( ret = ctr_drbg_random( ctx, buf, CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200396 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000397
398 if( fwrite( buf, 1, CTR_DRBG_MAX_INPUT, f ) != CTR_DRBG_MAX_INPUT )
399 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100400 ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR;
401 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000402 }
403
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200404 ret = 0;
405
406exit:
Paul Bakkerfc754a92011-12-05 13:23:51 +0000407 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200408 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000409}
410
411int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path )
412{
413 FILE *f;
414 size_t n;
415 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
416
417 if( ( f = fopen( path, "rb" ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000418 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000419
420 fseek( f, 0, SEEK_END );
421 n = (size_t) ftell( f );
422 fseek( f, 0, SEEK_SET );
423
424 if( n > CTR_DRBG_MAX_INPUT )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200425 {
426 fclose( f );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000427 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200428 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000429
430 if( fread( buf, 1, n, f ) != n )
431 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100432 fclose( f );
433 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000434 }
435
Paul Bakkerfc754a92011-12-05 13:23:51 +0000436 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200437
438 ctr_drbg_update( ctx, buf, n );
439
Paul Bakkerfc754a92011-12-05 13:23:51 +0000440 return( ctr_drbg_write_seed_file( ctx, path ) );
441}
442#endif /* POLARSSL_FS_IO */
443
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000444#if defined(POLARSSL_SELF_TEST)
445
446#include <stdio.h>
447
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100448static unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000449 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
450 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
451 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
452 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
453 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
454 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
455 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
456 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
457 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
458 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
459 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
460 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
461
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100462static unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000463 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
464 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
465 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
466 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
467 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
468 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
469 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
470 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
471
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100472static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000473 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
474 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
475
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100476static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000477 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
478 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
479
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100480static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000481 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
482 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
483
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100484static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000485 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
486 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
487
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100488static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200489static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
490 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000491{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100492 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000493 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100494 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000495 return( 0 );
496}
497
Paul Bakker7dc4c442014-02-01 22:50:26 +0100498#define CHK( c ) if( (c) != 0 ) \
499 { \
500 if( verbose != 0 ) \
501 polarssl_printf( "failed\n" ); \
502 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100503 }
504
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000505/*
506 * Checkup routine
507 */
508int ctr_drbg_self_test( int verbose )
509{
510 ctr_drbg_context ctx;
511 unsigned char buf[16];
512
513 /*
514 * Based on a NIST CTR_DRBG test vector (PR = True)
515 */
516 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100517 polarssl_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000518
519 test_offset = 0;
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100520 CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
521 entropy_source_pr, nonce_pers_pr, 16, 32 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000522 ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100523 CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) );
524 CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) );
525 CHK( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000526
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000527 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100528 polarssl_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000529
530 /*
531 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
532 */
533 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100534 polarssl_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000535
536 test_offset = 0;
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100537 CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
538 entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
539 CHK( ctr_drbg_random( &ctx, buf, 16 ) );
540 CHK( ctr_drbg_reseed( &ctx, NULL, 0 ) );
541 CHK( ctr_drbg_random( &ctx, buf, 16 ) );
542 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000543
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000544 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100545 polarssl_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000546
547 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100548 polarssl_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000549
550 return( 0 );
551}
Paul Bakker9af723c2014-05-01 13:03:14 +0200552#endif /* POLARSSL_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000553
Paul Bakker9af723c2014-05-01 13:03:14 +0200554#endif /* POLARSSL_CTR_DRBG_C */