blob: 91e061567b9a3253f2c692916b3690ea64d4313c [file] [log] [blame]
Paul Bakker0e04d0e2011-11-27 14:46:59 +00001/*
2 * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
3 *
Paul Bakker7dc4c442014-02-01 22:50:26 +01004 * Copyright (C) 2006-2014, Brainspark B.V.
Paul Bakker0e04d0e2011-11-27 14:46:59 +00005 *
6 * This file is part of PolarSSL (http://www.polarssl.org)
7 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
8 *
9 * All rights reserved.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 */
25/*
26 * The NIST SP 800-90 DRBGs are described in the following publucation.
27 *
28 * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
29 */
30
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020031#if !defined(POLARSSL_CONFIG_FILE)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000032#include "polarssl/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020033#else
34#include POLARSSL_CONFIG_FILE
35#endif
Paul Bakker0e04d0e2011-11-27 14:46:59 +000036
37#if defined(POLARSSL_CTR_DRBG_C)
38
39#include "polarssl/ctr_drbg.h"
40
Paul Bakkerfc754a92011-12-05 13:23:51 +000041#if defined(POLARSSL_FS_IO)
42#include <stdio.h>
43#endif
44
Paul Bakker7dc4c442014-02-01 22:50:26 +010045#if defined(POLARSSL_PLATFORM_C)
46#include "polarssl/platform.h"
47#else
48#define polarssl_printf printf
49#endif
50
Paul Bakkerfff03662014-06-18 16:21:25 +020051/* Implementation that should never be optimized out by the compiler */
52static void polarssl_zeroize( void *v, size_t n ) {
53 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
54}
55
Paul Bakker18d32912011-12-10 21:42:49 +000056/*
57 * Non-public function wrapped by ctr_crbg_init(). Necessary to allow NIST
58 * tests to succeed (which require known length fixed entropy)
59 */
Paul Bakker534f82c2013-06-25 16:47:55 +020060int ctr_drbg_init_entropy_len(
Paul Bakker18d32912011-12-10 21:42:49 +000061 ctr_drbg_context *ctx,
Paul Bakker0e04d0e2011-11-27 14:46:59 +000062 int (*f_entropy)(void *, unsigned char *, size_t),
63 void *p_entropy,
Paul Bakker1bc9efc2011-12-03 11:29:32 +000064 const unsigned char *custom,
Paul Bakker18d32912011-12-10 21:42:49 +000065 size_t len,
66 size_t entropy_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000067{
68 int ret;
Paul Bakker2bc7cf12011-11-29 10:50:51 +000069 unsigned char key[CTR_DRBG_KEYSIZE];
Paul Bakker0e04d0e2011-11-27 14:46:59 +000070
71 memset( ctx, 0, sizeof(ctr_drbg_context) );
Paul Bakker2bc7cf12011-11-29 10:50:51 +000072 memset( key, 0, CTR_DRBG_KEYSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000073
Paul Bakkerc7ea99a2014-06-18 11:12:03 +020074 aes_init( &ctx->aes_ctx );
75
Paul Bakker0e04d0e2011-11-27 14:46:59 +000076 ctx->f_entropy = f_entropy;
77 ctx->p_entropy = p_entropy;
78
Paul Bakker18d32912011-12-10 21:42:49 +000079 ctx->entropy_len = entropy_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +000080 ctx->reseed_interval = CTR_DRBG_RESEED_INTERVAL;
81
82 /*
83 * Initialize with an empty key
84 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +000085 aes_setkey_enc( &ctx->aes_ctx, key, CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000086
87 if( ( ret = ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
88 return( ret );
89
90 return( 0 );
91}
92
Paul Bakker18d32912011-12-10 21:42:49 +000093int ctr_drbg_init( ctr_drbg_context *ctx,
94 int (*f_entropy)(void *, unsigned char *, size_t),
95 void *p_entropy,
96 const unsigned char *custom,
97 size_t len )
98{
99 return( ctr_drbg_init_entropy_len( ctx, f_entropy, p_entropy, custom, len,
100 CTR_DRBG_ENTROPY_LEN ) );
101}
102
Paul Bakkerfff03662014-06-18 16:21:25 +0200103void ctr_drbg_free( ctr_drbg_context *ctx )
104{
105 if( ctx == NULL )
106 return;
107
108 aes_free( &ctx->aes_ctx );
109 polarssl_zeroize( ctx, sizeof( ctr_drbg_context ) );
110}
111
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000112void ctr_drbg_set_prediction_resistance( ctr_drbg_context *ctx, int resistance )
113{
114 ctx->prediction_resistance = resistance;
115}
116
117void ctr_drbg_set_entropy_len( ctr_drbg_context *ctx, size_t len )
118{
119 ctx->entropy_len = len;
120}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200121
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000122void ctr_drbg_set_reseed_interval( ctr_drbg_context *ctx, int interval )
123{
124 ctx->reseed_interval = interval;
125}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200126
127static int block_cipher_df( unsigned char *output,
128 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000129{
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000130 unsigned char buf[CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000131 unsigned char tmp[CTR_DRBG_SEEDLEN];
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000132 unsigned char key[CTR_DRBG_KEYSIZE];
133 unsigned char chain[CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100134 unsigned char *p, *iv;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000135 aes_context aes_ctx;
136
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200137 int i, j;
138 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000139
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100140 if( data_len > CTR_DRBG_MAX_SEED_INPUT )
141 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
142
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000143 memset( buf, 0, CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16 );
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200144 aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000145
146 /*
147 * Construct IV (16 bytes) and S in buffer
148 * IV = Counter (in 32-bits) padded to 16 with zeroes
149 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
150 * data || 0x80
151 * (Total is padded to a multiple of 16-bytes with zeroes)
152 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000153 p = buf + CTR_DRBG_BLOCKSIZE;
154 *p++ = ( data_len >> 24 ) & 0xff;
155 *p++ = ( data_len >> 16 ) & 0xff;
156 *p++ = ( data_len >> 8 ) & 0xff;
157 *p++ = ( data_len ) & 0xff;
158 p += 3;
159 *p++ = CTR_DRBG_SEEDLEN;
160 memcpy( p, data, data_len );
161 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000162
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000163 buf_len = CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000164
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000165 for( i = 0; i < CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000166 key[i] = i;
167
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000168 aes_setkey_enc( &aes_ctx, key, CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000169
170 /*
171 * Reduce data to POLARSSL_CTR_DRBG_SEEDLEN bytes of data
172 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000173 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000174 {
175 p = buf;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000176 memset( chain, 0, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000177 use_len = buf_len;
178
179 while( use_len > 0 )
180 {
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000181 for( i = 0; i < CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000182 chain[i] ^= p[i];
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000183 p += CTR_DRBG_BLOCKSIZE;
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200184 use_len -= ( use_len >= CTR_DRBG_BLOCKSIZE ) ?
185 CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000186
187 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, chain, chain );
188 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200189
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000190 memcpy( tmp + j, chain, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000191
192 /*
193 * Update IV
194 */
195 buf[3]++;
196 }
197
198 /*
199 * Do final encryption with reduced data
200 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000201 aes_setkey_enc( &aes_ctx, tmp, CTR_DRBG_KEYBITS );
202 iv = tmp + CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000203 p = output;
204
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000205 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000206 {
207 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, iv, iv );
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000208 memcpy( p, iv, CTR_DRBG_BLOCKSIZE );
209 p += CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000210 }
211
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200212 aes_free( &aes_ctx );
213
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000214 return( 0 );
215}
216
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200217static int ctr_drbg_update_internal( ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000218 const unsigned char data[CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000219{
220 unsigned char tmp[CTR_DRBG_SEEDLEN];
221 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000222 int i, j;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000223
224 memset( tmp, 0, CTR_DRBG_SEEDLEN );
225
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000226 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000227 {
228 /*
229 * Increase counter
230 */
Paul Bakker9a736322012-11-14 12:39:52 +0000231 for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000232 if( ++ctx->counter[i - 1] != 0 )
233 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000234
235 /*
236 * Crypt counter block
237 */
238 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, p );
239
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000240 p += CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000241 }
242
243 for( i = 0; i < CTR_DRBG_SEEDLEN; i++ )
244 tmp[i] ^= data[i];
245
246 /*
247 * Update key and counter
248 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000249 aes_setkey_enc( &ctx->aes_ctx, tmp, CTR_DRBG_KEYBITS );
250 memcpy( ctx->counter, tmp + CTR_DRBG_KEYSIZE, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000251
252 return( 0 );
253}
254
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000255void ctr_drbg_update( ctr_drbg_context *ctx,
256 const unsigned char *additional, size_t add_len )
257{
258 unsigned char add_input[CTR_DRBG_SEEDLEN];
259
260 if( add_len > 0 )
261 {
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100262 /* MAX_INPUT would be more logical here, but we have to match
263 * block_cipher_df()'s limits since we can't propagate errors */
264 if( add_len > CTR_DRBG_MAX_SEED_INPUT )
265 add_len = CTR_DRBG_MAX_SEED_INPUT;
266
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000267 block_cipher_df( add_input, additional, add_len );
268 ctr_drbg_update_internal( ctx, add_input );
269 }
270}
271
272int ctr_drbg_reseed( ctr_drbg_context *ctx,
273 const unsigned char *additional, size_t len )
274{
275 unsigned char seed[CTR_DRBG_MAX_SEED_INPUT];
276 size_t seedlen = 0;
277
278 if( ctx->entropy_len + len > CTR_DRBG_MAX_SEED_INPUT )
279 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
280
281 memset( seed, 0, CTR_DRBG_MAX_SEED_INPUT );
282
283 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200284 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000285 */
286 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
287 ctx->entropy_len ) )
288 {
289 return( POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
290 }
291
292 seedlen += ctx->entropy_len;
293
294 /*
295 * Add additional data
296 */
297 if( additional && len )
298 {
299 memcpy( seed + seedlen, additional, len );
300 seedlen += len;
301 }
302
303 /*
304 * Reduce to 384 bits
305 */
306 block_cipher_df( seed, seed, seedlen );
307
308 /*
309 * Update state
310 */
311 ctr_drbg_update_internal( ctx, seed );
312 ctx->reseed_counter = 1;
313
314 return( 0 );
315}
Paul Bakker9af723c2014-05-01 13:03:14 +0200316
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000317int ctr_drbg_random_with_add( void *p_rng,
318 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000319 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000320{
321 int ret = 0;
322 ctr_drbg_context *ctx = (ctr_drbg_context *) p_rng;
323 unsigned char add_input[CTR_DRBG_SEEDLEN];
324 unsigned char *p = output;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000325 unsigned char tmp[CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000326 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000327 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000328
329 if( output_len > CTR_DRBG_MAX_REQUEST )
330 return( POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG );
331
332 if( add_len > CTR_DRBG_MAX_INPUT )
333 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
334
335 memset( add_input, 0, CTR_DRBG_SEEDLEN );
336
337 if( ctx->reseed_counter > ctx->reseed_interval ||
338 ctx->prediction_resistance )
339 {
340 if( ( ret = ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
341 return( ret );
342
343 add_len = 0;
344 }
345
346 if( add_len > 0 )
347 {
348 block_cipher_df( add_input, additional, add_len );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000349 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000350 }
351
352 while( output_len > 0 )
353 {
354 /*
355 * Increase counter
356 */
Paul Bakker369e14b2012-04-18 14:16:09 +0000357 for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
358 if( ++ctx->counter[i - 1] != 0 )
359 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000360
361 /*
362 * Crypt counter block
363 */
364 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, tmp );
365
Paul Bakker66d5d072014-06-17 16:39:18 +0200366 use_len = ( output_len > CTR_DRBG_BLOCKSIZE ) ? CTR_DRBG_BLOCKSIZE :
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200367 output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000368 /*
369 * Copy random block to destination
370 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000371 memcpy( p, tmp, use_len );
372 p += use_len;
373 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000374 }
375
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000376 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000377
378 ctx->reseed_counter++;
379
380 return( 0 );
381}
382
383int ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
384{
385 return ctr_drbg_random_with_add( p_rng, output, output_len, NULL, 0 );
386}
387
Paul Bakkerfc754a92011-12-05 13:23:51 +0000388#if defined(POLARSSL_FS_IO)
389int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path )
390{
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200391 int ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000392 FILE *f;
393 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
394
395 if( ( f = fopen( path, "wb" ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000396 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000397
398 if( ( ret = ctr_drbg_random( ctx, buf, CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200399 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000400
401 if( fwrite( buf, 1, CTR_DRBG_MAX_INPUT, f ) != CTR_DRBG_MAX_INPUT )
402 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100403 ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR;
404 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000405 }
406
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200407 ret = 0;
408
409exit:
Paul Bakkerfc754a92011-12-05 13:23:51 +0000410 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200411 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000412}
413
414int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path )
415{
416 FILE *f;
417 size_t n;
418 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
419
420 if( ( f = fopen( path, "rb" ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000421 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000422
423 fseek( f, 0, SEEK_END );
424 n = (size_t) ftell( f );
425 fseek( f, 0, SEEK_SET );
426
427 if( n > CTR_DRBG_MAX_INPUT )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200428 {
429 fclose( f );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000430 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200431 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000432
433 if( fread( buf, 1, n, f ) != n )
434 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100435 fclose( f );
436 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000437 }
438
Paul Bakkerfc754a92011-12-05 13:23:51 +0000439 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200440
441 ctr_drbg_update( ctx, buf, n );
442
Paul Bakkerfc754a92011-12-05 13:23:51 +0000443 return( ctr_drbg_write_seed_file( ctx, path ) );
444}
445#endif /* POLARSSL_FS_IO */
446
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000447#if defined(POLARSSL_SELF_TEST)
448
449#include <stdio.h>
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 */