PolarSSL v1.2.8
ctr_drbg.c
Go to the documentation of this file.
1 /*
2  * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
3  *
4  * Copyright (C) 2006-2011, Brainspark B.V.
5  *
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 
31 #include "polarssl/config.h"
32 
33 #if defined(POLARSSL_CTR_DRBG_C)
34 
35 #include "polarssl/ctr_drbg.h"
36 
37 #if defined(POLARSSL_FS_IO)
38 #include <stdio.h>
39 #endif
40 
41 /*
42  * Non-public function wrapped by ctr_crbg_init(). Necessary to allow NIST
43  * tests to succeed (which require known length fixed entropy)
44  */
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 )
52 {
53  int ret;
54  unsigned char key[CTR_DRBG_KEYSIZE];
55 
56  memset( ctx, 0, sizeof(ctr_drbg_context) );
57  memset( key, 0, CTR_DRBG_KEYSIZE );
58 
59  ctx->f_entropy = f_entropy;
60  ctx->p_entropy = p_entropy;
61 
62  ctx->entropy_len = entropy_len;
64 
65  /*
66  * Initialize with an empty key
67  */
69 
70  if( ( ret = ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
71  return( ret );
72 
73  return( 0 );
74 }
75 
77  int (*f_entropy)(void *, unsigned char *, size_t),
78  void *p_entropy,
79  const unsigned char *custom,
80  size_t len )
81 {
82  return( ctr_drbg_init_entropy_len( ctx, f_entropy, p_entropy, custom, len,
84 }
85 
86 void ctr_drbg_set_prediction_resistance( ctr_drbg_context *ctx, int resistance )
87 {
88  ctx->prediction_resistance = resistance;
89 }
90 
91 void ctr_drbg_set_entropy_len( ctr_drbg_context *ctx, size_t len )
92 {
93  ctx->entropy_len = len;
94 }
95 
96 void ctr_drbg_set_reseed_interval( ctr_drbg_context *ctx, int interval )
97 {
98  ctx->reseed_interval = interval;
99 }
100 
101 int block_cipher_df( unsigned char *output,
102  const unsigned char *data, size_t data_len )
103 {
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;
110 
111  int i, j, buf_len, use_len;
112 
113  memset( buf, 0, CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16 );
114 
115  /*
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)
121  */
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;
131 
132  buf_len = CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
133 
134  for( i = 0; i < CTR_DRBG_KEYSIZE; i++ )
135  key[i] = i;
136 
137  aes_setkey_enc( &aes_ctx, key, CTR_DRBG_KEYBITS );
138 
139  /*
140  * Reduce data to POLARSSL_CTR_DRBG_SEEDLEN bytes of data
141  */
142  for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
143  {
144  p = buf;
145  memset( chain, 0, CTR_DRBG_BLOCKSIZE );
146  use_len = buf_len;
147 
148  while( use_len > 0 )
149  {
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;
154 
155  aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, chain, chain );
156  }
157 
158  memcpy( tmp + j, chain, CTR_DRBG_BLOCKSIZE );
159 
160  /*
161  * Update IV
162  */
163  buf[3]++;
164  }
165 
166  /*
167  * Do final encryption with reduced data
168  */
169  aes_setkey_enc( &aes_ctx, tmp, CTR_DRBG_KEYBITS );
170  iv = tmp + CTR_DRBG_KEYSIZE;
171  p = output;
172 
173  for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
174  {
175  aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, iv, iv );
176  memcpy( p, iv, CTR_DRBG_BLOCKSIZE );
177  p += CTR_DRBG_BLOCKSIZE;
178  }
179 
180  return( 0 );
181 }
182 
183 int ctr_drbg_update_internal( ctr_drbg_context *ctx,
184  const unsigned char data[CTR_DRBG_SEEDLEN] )
185 {
186  unsigned char tmp[CTR_DRBG_SEEDLEN];
187  unsigned char *p = tmp;
188  int i, j;
189 
190  memset( tmp, 0, CTR_DRBG_SEEDLEN );
191 
192  for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
193  {
194  /*
195  * Increase counter
196  */
197  for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
198  if( ++ctx->counter[i - 1] != 0 )
199  break;
200 
201  /*
202  * Crypt counter block
203  */
204  aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, p );
205 
206  p += CTR_DRBG_BLOCKSIZE;
207  }
208 
209  for( i = 0; i < CTR_DRBG_SEEDLEN; i++ )
210  tmp[i] ^= data[i];
211 
212  /*
213  * Update key and counter
214  */
215  aes_setkey_enc( &ctx->aes_ctx, tmp, CTR_DRBG_KEYBITS );
216  memcpy( ctx->counter, tmp + CTR_DRBG_KEYSIZE, CTR_DRBG_BLOCKSIZE );
217 
218  return( 0 );
219 }
220 
222  const unsigned char *additional, size_t add_len )
223 {
224  unsigned char add_input[CTR_DRBG_SEEDLEN];
225 
226  if( add_len > 0 )
227  {
228  block_cipher_df( add_input, additional, add_len );
229  ctr_drbg_update_internal( ctx, add_input );
230  }
231 }
232 
234  const unsigned char *additional, size_t len )
235 {
236  unsigned char seed[CTR_DRBG_MAX_SEED_INPUT];
237  size_t seedlen = 0;
238 
239  if( ctx->entropy_len + len > CTR_DRBG_MAX_SEED_INPUT )
241 
242  memset( seed, 0, CTR_DRBG_MAX_SEED_INPUT );
243 
244  /*
245  * Gather enropy_len bytes of entropy to seed state
246  */
247  if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
248  ctx->entropy_len ) )
249  {
251  }
252 
253  seedlen += ctx->entropy_len;
254 
255  /*
256  * Add additional data
257  */
258  if( additional && len )
259  {
260  memcpy( seed + seedlen, additional, len );
261  seedlen += len;
262  }
263 
264  /*
265  * Reduce to 384 bits
266  */
267  block_cipher_df( seed, seed, seedlen );
268 
269  /*
270  * Update state
271  */
272  ctr_drbg_update_internal( ctx, seed );
273  ctx->reseed_counter = 1;
274 
275  return( 0 );
276 }
277 
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 )
281 {
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;
289 
290  if( output_len > CTR_DRBG_MAX_REQUEST )
292 
293  if( add_len > CTR_DRBG_MAX_INPUT )
295 
296  memset( add_input, 0, CTR_DRBG_SEEDLEN );
297 
298  if( ctx->reseed_counter > ctx->reseed_interval ||
299  ctx->prediction_resistance )
300  {
301  if( ( ret = ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
302  return( ret );
303 
304  add_len = 0;
305  }
306 
307  if( add_len > 0 )
308  {
309  block_cipher_df( add_input, additional, add_len );
310  ctr_drbg_update_internal( ctx, add_input );
311  }
312 
313  while( output_len > 0 )
314  {
315  /*
316  * Increase counter
317  */
318  for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
319  if( ++ctx->counter[i - 1] != 0 )
320  break;
321 
322  /*
323  * Crypt counter block
324  */
325  aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, tmp );
326 
327  use_len = (output_len > CTR_DRBG_BLOCKSIZE ) ? CTR_DRBG_BLOCKSIZE : output_len;
328  /*
329  * Copy random block to destination
330  */
331  memcpy( p, tmp, use_len );
332  p += use_len;
333  output_len -= use_len;
334  }
335 
336  ctr_drbg_update_internal( ctx, add_input );
337 
338  ctx->reseed_counter++;
339 
340  return( 0 );
341 }
342 
343 int ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
344 {
345  return ctr_drbg_random_with_add( p_rng, output, output_len, NULL, 0 );
346 }
347 
348 #if defined(POLARSSL_FS_IO)
349 int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path )
350 {
351  int ret;
352  FILE *f;
353  unsigned char buf[ CTR_DRBG_MAX_INPUT ];
354 
355  if( ( f = fopen( path, "wb" ) ) == NULL )
357 
358  if( ( ret = ctr_drbg_random( ctx, buf, CTR_DRBG_MAX_INPUT ) ) != 0 )
359  return( ret );
360 
361  if( fwrite( buf, 1, CTR_DRBG_MAX_INPUT, f ) != CTR_DRBG_MAX_INPUT )
362  {
363  fclose( f );
365  }
366 
367  fclose( f );
368  return( 0 );
369 }
370 
371 int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path )
372 {
373  FILE *f;
374  size_t n;
375  unsigned char buf[ CTR_DRBG_MAX_INPUT ];
376 
377  if( ( f = fopen( path, "rb" ) ) == NULL )
379 
380  fseek( f, 0, SEEK_END );
381  n = (size_t) ftell( f );
382  fseek( f, 0, SEEK_SET );
383 
384  if( n > CTR_DRBG_MAX_INPUT )
386 
387  if( fread( buf, 1, n, f ) != n )
388  {
389  fclose( f );
391  }
392 
393  ctr_drbg_update( ctx, buf, n );
394 
395  fclose( f );
396 
397  return( ctr_drbg_write_seed_file( ctx, path ) );
398 }
399 #endif /* POLARSSL_FS_IO */
400 
401 #if defined(POLARSSL_SELF_TEST)
402 
403 #include <stdio.h>
404 
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 };
418 
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 };
428 
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 };
432 
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 };
436 
437 unsigned char result_pr[16] =
438  { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
439  0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
440 
441 unsigned char result_nopr[16] =
442  { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
443  0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
444 
445 int test_offset;
446 int ctr_drbg_self_test_entropy( void *data, unsigned char *buf, size_t len )
447 {
448  unsigned char *p = data;
449  memcpy( buf, p + test_offset, len );
450  test_offset += 32;
451  return( 0 );
452 }
453 
454 /*
455  * Checkup routine
456  */
457 int ctr_drbg_self_test( int verbose )
458 {
459  ctr_drbg_context ctx;
460  unsigned char buf[16];
461 
462  /*
463  * Based on a NIST CTR_DRBG test vector (PR = True)
464  */
465  if( verbose != 0 )
466  printf( " CTR_DRBG (PR = TRUE) : " );
467 
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 )
470  {
471  if( verbose != 0 )
472  printf( "failed\n" );
473 
474  return( 1 );
475  }
477 
478  if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 )
479  {
480  if( verbose != 0 )
481  printf( "failed\n" );
482 
483  return( 1 );
484  }
485 
486  if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 )
487  {
488  if( verbose != 0 )
489  printf( "failed\n" );
490 
491  return( 1 );
492  }
493 
494  if( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) != 0 )
495  {
496  if( verbose != 0 )
497  printf( "failed\n" );
498 
499  return( 1 );
500  }
501 
502  if( verbose != 0 )
503  printf( "passed\n" );
504 
505  /*
506  * Based on a NIST CTR_DRBG test vector (PR = FALSE)
507  */
508  if( verbose != 0 )
509  printf( " CTR_DRBG (PR = FALSE): " );
510 
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 )
513  {
514  if( verbose != 0 )
515  printf( "failed\n" );
516 
517  return( 1 );
518  }
519 
520  if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
521  {
522  if( verbose != 0 )
523  printf( "failed\n" );
524 
525  return( 1 );
526  }
527 
528  if( ctr_drbg_reseed( &ctx, NULL, 0 ) != 0 )
529  {
530  if( verbose != 0 )
531  printf( "failed\n" );
532 
533  return( 1 );
534  }
535 
536  if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
537  {
538  if( verbose != 0 )
539  printf( "failed\n" );
540 
541  return( 1 );
542  }
543 
544  if( memcmp( buf, result_nopr, 16 ) != 0 )
545  {
546  if( verbose != 0 )
547  printf( "failed\n" );
548 
549  return( 1 );
550  }
551 
552  if( verbose != 0 )
553  printf( "passed\n" );
554 
555  if( verbose != 0 )
556  printf( "\n" );
557 
558  return( 0 );
559 }
560 #endif
561 
562 #endif