initial commit; it works
[psslcertgen.git] / src / libpolarssl / ctr_drbg.c
blob06b20272bdeef866295fca4f820304e874d0db62
1 /*
2 * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
4 * Copyright (C) 2006-2011, Brainspark B.V.
6 * This file is part of PolarSSL (http://www.polarssl.org)
7 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
9 * All rights reserved.
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.
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.
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.
26 * The NIST SP 800-90 DRBGs are described in the following publucation.
28 * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
31 #include "config.h"
33 #if defined(POLARSSL_CTR_DRBG_C)
35 #include "ctr_drbg.h"
37 #if defined(POLARSSL_FS_IO)
38 #include <stdio.h>
39 #endif
42 * Non-public function wrapped by ctr_crbg_init(). Necessary to allow NIST
43 * tests to succeed (which require known length fixed entropy)
45 int ctr_drbg_init_entropy_len(
46 ctr_drbg_context *ctx,
47 int (*f_entropy)(void *, unsigned char *, size_t),
48 void *p_entropy,
49 const unsigned char *custom,
50 size_t len,
51 size_t entropy_len )
53 int ret;
54 unsigned char key[CTR_DRBG_KEYSIZE];
56 memset( ctx, 0, sizeof(ctr_drbg_context) );
57 memset( key, 0, CTR_DRBG_KEYSIZE );
59 ctx->f_entropy = f_entropy;
60 ctx->p_entropy = p_entropy;
62 ctx->entropy_len = entropy_len;
63 ctx->reseed_interval = CTR_DRBG_RESEED_INTERVAL;
66 * Initialize with an empty key
68 aes_setkey_enc( &ctx->aes_ctx, key, CTR_DRBG_KEYBITS );
70 if( ( ret = ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
71 return( ret );
73 return( 0 );
76 int ctr_drbg_init( ctr_drbg_context *ctx,
77 int (*f_entropy)(void *, unsigned char *, size_t),
78 void *p_entropy,
79 const unsigned char *custom,
80 size_t len )
82 return( ctr_drbg_init_entropy_len( ctx, f_entropy, p_entropy, custom, len,
83 CTR_DRBG_ENTROPY_LEN ) );
86 void ctr_drbg_set_prediction_resistance( ctr_drbg_context *ctx, int resistance )
88 ctx->prediction_resistance = resistance;
91 void ctr_drbg_set_entropy_len( ctr_drbg_context *ctx, size_t len )
93 ctx->entropy_len = len;
96 void ctr_drbg_set_reseed_interval( ctr_drbg_context *ctx, int interval )
98 ctx->reseed_interval = interval;
101 int block_cipher_df( unsigned char *output,
102 const unsigned char *data, size_t data_len )
104 unsigned char buf[CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16];
105 unsigned char tmp[CTR_DRBG_SEEDLEN];
106 unsigned char key[CTR_DRBG_KEYSIZE];
107 unsigned char chain[CTR_DRBG_BLOCKSIZE];
108 unsigned char *p = buf, *iv;
109 aes_context aes_ctx;
111 int i, j, buf_len, use_len;
113 memset( buf, 0, CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16 );
116 * Construct IV (16 bytes) and S in buffer
117 * IV = Counter (in 32-bits) padded to 16 with zeroes
118 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
119 * data || 0x80
120 * (Total is padded to a multiple of 16-bytes with zeroes)
122 p = buf + CTR_DRBG_BLOCKSIZE;
123 *p++ = ( data_len >> 24 ) & 0xff;
124 *p++ = ( data_len >> 16 ) & 0xff;
125 *p++ = ( data_len >> 8 ) & 0xff;
126 *p++ = ( data_len ) & 0xff;
127 p += 3;
128 *p++ = CTR_DRBG_SEEDLEN;
129 memcpy( p, data, data_len );
130 p[data_len] = 0x80;
132 buf_len = CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
134 for( i = 0; i < CTR_DRBG_KEYSIZE; i++ )
135 key[i] = i;
137 aes_setkey_enc( &aes_ctx, key, CTR_DRBG_KEYBITS );
140 * Reduce data to POLARSSL_CTR_DRBG_SEEDLEN bytes of data
142 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
144 p = buf;
145 memset( chain, 0, CTR_DRBG_BLOCKSIZE );
146 use_len = buf_len;
148 while( use_len > 0 )
150 for( i = 0; i < CTR_DRBG_BLOCKSIZE; i++ )
151 chain[i] ^= p[i];
152 p += CTR_DRBG_BLOCKSIZE;
153 use_len -= CTR_DRBG_BLOCKSIZE;
155 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, chain, chain );
158 memcpy( tmp + j, chain, CTR_DRBG_BLOCKSIZE );
161 * Update IV
163 buf[3]++;
167 * Do final encryption with reduced data
169 aes_setkey_enc( &aes_ctx, tmp, CTR_DRBG_KEYBITS );
170 iv = tmp + CTR_DRBG_KEYSIZE;
171 p = output;
173 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
175 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, iv, iv );
176 memcpy( p, iv, CTR_DRBG_BLOCKSIZE );
177 p += CTR_DRBG_BLOCKSIZE;
180 return( 0 );
183 int ctr_drbg_update_internal( ctr_drbg_context *ctx,
184 const unsigned char data[CTR_DRBG_SEEDLEN] )
186 unsigned char tmp[CTR_DRBG_SEEDLEN];
187 unsigned char *p = tmp;
188 int i, j;
190 memset( tmp, 0, CTR_DRBG_SEEDLEN );
192 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
195 * Increase counter
197 for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
198 if( ++ctx->counter[i - 1] != 0 )
199 break;
202 * Crypt counter block
204 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, p );
206 p += CTR_DRBG_BLOCKSIZE;
209 for( i = 0; i < CTR_DRBG_SEEDLEN; i++ )
210 tmp[i] ^= data[i];
213 * Update key and counter
215 aes_setkey_enc( &ctx->aes_ctx, tmp, CTR_DRBG_KEYBITS );
216 memcpy( ctx->counter, tmp + CTR_DRBG_KEYSIZE, CTR_DRBG_BLOCKSIZE );
218 return( 0 );
221 void ctr_drbg_update( ctr_drbg_context *ctx,
222 const unsigned char *additional, size_t add_len )
224 unsigned char add_input[CTR_DRBG_SEEDLEN];
226 if( add_len > 0 )
228 block_cipher_df( add_input, additional, add_len );
229 ctr_drbg_update_internal( ctx, add_input );
233 int ctr_drbg_reseed( ctr_drbg_context *ctx,
234 const unsigned char *additional, size_t len )
236 unsigned char seed[CTR_DRBG_MAX_SEED_INPUT];
237 size_t seedlen = 0;
239 if( ctx->entropy_len + len > CTR_DRBG_MAX_SEED_INPUT )
240 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
242 memset( seed, 0, CTR_DRBG_MAX_SEED_INPUT );
245 * Gather enropy_len bytes of entropy to seed state
247 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
248 ctx->entropy_len ) )
250 return( POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
253 seedlen += ctx->entropy_len;
256 * Add additional data
258 if( additional && len )
260 memcpy( seed + seedlen, additional, len );
261 seedlen += len;
265 * Reduce to 384 bits
267 block_cipher_df( seed, seed, seedlen );
270 * Update state
272 ctr_drbg_update_internal( ctx, seed );
273 ctx->reseed_counter = 1;
275 return( 0 );
278 int ctr_drbg_random_with_add( void *p_rng,
279 unsigned char *output, size_t output_len,
280 const unsigned char *additional, size_t add_len )
282 int ret = 0;
283 ctr_drbg_context *ctx = (ctr_drbg_context *) p_rng;
284 unsigned char add_input[CTR_DRBG_SEEDLEN];
285 unsigned char *p = output;
286 unsigned char tmp[CTR_DRBG_BLOCKSIZE];
287 int i;
288 size_t use_len;
290 if( output_len > CTR_DRBG_MAX_REQUEST )
291 return( POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG );
293 if( add_len > CTR_DRBG_MAX_INPUT )
294 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
296 memset( add_input, 0, CTR_DRBG_SEEDLEN );
298 if( ctx->reseed_counter > ctx->reseed_interval ||
299 ctx->prediction_resistance )
301 if( ( ret = ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
302 return( ret );
304 add_len = 0;
307 if( add_len > 0 )
309 block_cipher_df( add_input, additional, add_len );
310 ctr_drbg_update_internal( ctx, add_input );
313 while( output_len > 0 )
316 * Increase counter
318 for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
319 if( ++ctx->counter[i - 1] != 0 )
320 break;
323 * Crypt counter block
325 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, tmp );
327 use_len = (output_len > CTR_DRBG_BLOCKSIZE ) ? CTR_DRBG_BLOCKSIZE : output_len;
329 * Copy random block to destination
331 memcpy( p, tmp, use_len );
332 p += use_len;
333 output_len -= use_len;
336 ctr_drbg_update_internal( ctx, add_input );
338 ctx->reseed_counter++;
340 return( 0 );
343 int ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
345 return ctr_drbg_random_with_add( p_rng, output, output_len, NULL, 0 );
348 #if defined(POLARSSL_FS_IO)
349 int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path )
351 int ret;
352 FILE *f;
353 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
355 if( ( f = fopen( path, "wb" ) ) == NULL )
356 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
358 if( ( ret = ctr_drbg_random( ctx, buf, CTR_DRBG_MAX_INPUT ) ) != 0 )
359 return( ret );
361 if( fwrite( buf, 1, CTR_DRBG_MAX_INPUT, f ) != CTR_DRBG_MAX_INPUT )
363 fclose( f );
364 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
367 fclose( f );
368 return( 0 );
371 int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path )
373 FILE *f;
374 size_t n;
375 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
377 if( ( f = fopen( path, "rb" ) ) == NULL )
378 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
380 fseek( f, 0, SEEK_END );
381 n = (size_t) ftell( f );
382 fseek( f, 0, SEEK_SET );
384 if( n > CTR_DRBG_MAX_INPUT )
385 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
387 if( fread( buf, 1, n, f ) != n )
389 fclose( f );
390 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
393 ctr_drbg_update( ctx, buf, n );
395 fclose( f );
397 return( ctr_drbg_write_seed_file( ctx, path ) );
399 #endif /* POLARSSL_FS_IO */
401 #if defined(POLARSSL_SELF_TEST)
403 #include <stdio.h>
405 unsigned char entropy_source_pr[96] =
406 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
407 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
408 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
409 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
410 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
411 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
412 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
413 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
414 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
415 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
416 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
417 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
419 unsigned char entropy_source_nopr[64] =
420 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
421 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
422 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
423 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
424 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
425 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
426 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
427 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
429 unsigned char nonce_pers_pr[16] =
430 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
431 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
433 unsigned char nonce_pers_nopr[16] =
434 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
435 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
437 unsigned char result_pr[16] =
438 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
439 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
441 unsigned char result_nopr[16] =
442 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
443 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
445 int test_offset;
446 int ctr_drbg_self_test_entropy( void *data, unsigned char *buf, size_t len )
448 unsigned char *p = data;
449 memcpy( buf, p + test_offset, len );
450 test_offset += 32;
451 return( 0 );
455 * Checkup routine
457 int ctr_drbg_self_test( int verbose )
459 ctr_drbg_context ctx;
460 unsigned char buf[16];
463 * Based on a NIST CTR_DRBG test vector (PR = True)
465 if( verbose != 0 )
466 printf( " CTR_DRBG (PR = TRUE) : " );
468 test_offset = 0;
469 if( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy, entropy_source_pr, nonce_pers_pr, 16, 32 ) != 0 )
471 if( verbose != 0 )
472 printf( "failed\n" );
474 return( 1 );
476 ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON );
478 if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 )
480 if( verbose != 0 )
481 printf( "failed\n" );
483 return( 1 );
486 if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 )
488 if( verbose != 0 )
489 printf( "failed\n" );
491 return( 1 );
494 if( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) != 0 )
496 if( verbose != 0 )
497 printf( "failed\n" );
499 return( 1 );
502 if( verbose != 0 )
503 printf( "passed\n" );
506 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
508 if( verbose != 0 )
509 printf( " CTR_DRBG (PR = FALSE): " );
511 test_offset = 0;
512 if( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy, entropy_source_nopr, nonce_pers_nopr, 16, 32 ) != 0 )
514 if( verbose != 0 )
515 printf( "failed\n" );
517 return( 1 );
520 if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
522 if( verbose != 0 )
523 printf( "failed\n" );
525 return( 1 );
528 if( ctr_drbg_reseed( &ctx, NULL, 0 ) != 0 )
530 if( verbose != 0 )
531 printf( "failed\n" );
533 return( 1 );
536 if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
538 if( verbose != 0 )
539 printf( "failed\n" );
541 return( 1 );
544 if( memcmp( buf, result_nopr, 16 ) != 0 )
546 if( verbose != 0 )
547 printf( "failed\n" );
549 return( 1 );
552 if( verbose != 0 )
553 printf( "passed\n" );
555 if( verbose != 0 )
556 printf( "\n" );
558 return( 0 );
560 #endif
562 #endif