PolarSSL v1.1.5
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 cb, 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  i = CTR_DRBG_BLOCKSIZE - 1;
198  do {
199  ctx->counter[i]++;
200  cb = ctx->counter[i] == 0;
201  } while( i-- && cb );
202 
203  /*
204  * Crypt counter block
205  */
206  aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, p );
207 
208  p += CTR_DRBG_BLOCKSIZE;
209  }
210 
211  for( i = 0; i < CTR_DRBG_SEEDLEN; i++ )
212  tmp[i] ^= data[i];
213 
214  /*
215  * Update key and counter
216  */
217  aes_setkey_enc( &ctx->aes_ctx, tmp, CTR_DRBG_KEYBITS );
218  memcpy( ctx->counter, tmp + CTR_DRBG_KEYSIZE, CTR_DRBG_BLOCKSIZE );
219 
220  return( 0 );
221 }
222 
224  const unsigned char *additional, size_t add_len )
225 {
226  unsigned char add_input[CTR_DRBG_SEEDLEN];
227 
228  if( add_len > 0 )
229  {
230  block_cipher_df( add_input, additional, add_len );
231  ctr_drbg_update_internal( ctx, add_input );
232  }
233 }
234 
236  const unsigned char *additional, size_t len )
237 {
238  unsigned char seed[CTR_DRBG_MAX_SEED_INPUT];
239  size_t seedlen = 0;
240 
241  if( ctx->entropy_len + len > CTR_DRBG_MAX_SEED_INPUT )
243 
244  memset( seed, 0, CTR_DRBG_MAX_SEED_INPUT );
245 
246  /*
247  * Gather enropy_len bytes of entropy to seed state
248  */
249  if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
250  ctx->entropy_len ) )
251  {
253  }
254 
255  seedlen += ctx->entropy_len;
256 
257  /*
258  * Add additional data
259  */
260  if( additional && len )
261  {
262  memcpy( seed + seedlen, additional, len );
263  seedlen += len;
264  }
265 
266  /*
267  * Reduce to 384 bits
268  */
269  block_cipher_df( seed, seed, seedlen );
270 
271  /*
272  * Update state
273  */
274  ctr_drbg_update_internal( ctx, seed );
275  ctx->reseed_counter = 1;
276 
277  return( 0 );
278 }
279 
280 int ctr_drbg_random_with_add( void *p_rng,
281  unsigned char *output, size_t output_len,
282  const unsigned char *additional, size_t add_len )
283 {
284  int ret = 0;
285  ctr_drbg_context *ctx = (ctr_drbg_context *) p_rng;
286  unsigned char add_input[CTR_DRBG_SEEDLEN];
287  unsigned char *p = output;
288  unsigned char tmp[CTR_DRBG_BLOCKSIZE];
289  int cb, i;
290  size_t use_len;
291 
292  if( output_len > CTR_DRBG_MAX_REQUEST )
294 
295  if( add_len > CTR_DRBG_MAX_INPUT )
297 
298  memset( add_input, 0, CTR_DRBG_SEEDLEN );
299 
300  if( ctx->reseed_counter > ctx->reseed_interval ||
301  ctx->prediction_resistance )
302  {
303  if( ( ret = ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
304  return( ret );
305 
306  add_len = 0;
307  }
308 
309  if( add_len > 0 )
310  {
311  block_cipher_df( add_input, additional, add_len );
312  ctr_drbg_update_internal( ctx, add_input );
313  }
314 
315  while( output_len > 0 )
316  {
317  /*
318  * Increase counter
319  */
320  i = CTR_DRBG_BLOCKSIZE - 1;
321  do {
322  ctx->counter[i]++;
323  cb = ctx->counter[i] == 0;
324  } while( i-- && cb );
325 
326  /*
327  * Crypt counter block
328  */
329  aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, tmp );
330 
331  use_len = (output_len > CTR_DRBG_BLOCKSIZE ) ? CTR_DRBG_BLOCKSIZE : output_len;
332  /*
333  * Copy random block to destination
334  */
335  memcpy( p, tmp, use_len );
336  p += use_len;
337  output_len -= use_len;
338  }
339 
340  ctr_drbg_update_internal( ctx, add_input );
341 
342  ctx->reseed_counter++;
343 
344  return( 0 );
345 }
346 
347 int ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
348 {
349  return ctr_drbg_random_with_add( p_rng, output, output_len, NULL, 0 );
350 }
351 
352 #if defined(POLARSSL_FS_IO)
353 int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path )
354 {
355  int ret;
356  FILE *f;
357  unsigned char buf[ CTR_DRBG_MAX_INPUT ];
358 
359  if( ( f = fopen( path, "wb" ) ) == NULL )
361 
362  if( ( ret = ctr_drbg_random( ctx, buf, CTR_DRBG_MAX_INPUT ) ) != 0 )
363  return( ret );
364 
365  if( fwrite( buf, 1, CTR_DRBG_MAX_INPUT, f ) != CTR_DRBG_MAX_INPUT )
366  {
367  fclose( f );
369  }
370 
371  fclose( f );
372  return( 0 );
373 }
374 
375 int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path )
376 {
377  FILE *f;
378  size_t n;
379  unsigned char buf[ CTR_DRBG_MAX_INPUT ];
380 
381  if( ( f = fopen( path, "rb" ) ) == NULL )
383 
384  fseek( f, 0, SEEK_END );
385  n = (size_t) ftell( f );
386  fseek( f, 0, SEEK_SET );
387 
388  if( n > CTR_DRBG_MAX_INPUT )
390 
391  if( fread( buf, 1, n, f ) != n )
392  {
393  fclose( f );
395  }
396 
397  ctr_drbg_update( ctx, buf, n );
398 
399  fclose( f );
400 
401  return( ctr_drbg_write_seed_file( ctx, path ) );
402 }
403 #endif /* POLARSSL_FS_IO */
404 
405 #if defined(POLARSSL_SELF_TEST)
406 
407 #include <stdio.h>
408 
409 unsigned char entropy_source_pr[96] =
410  { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
411  0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
412  0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
413  0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
414  0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
415  0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
416  0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
417  0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
418  0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
419  0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
420  0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
421  0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
422 
423 unsigned char entropy_source_nopr[64] =
424  { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
425  0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
426  0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
427  0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
428  0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
429  0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
430  0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
431  0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
432 
433 unsigned char nonce_pers_pr[16] =
434  { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
435  0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
436 
437 unsigned char nonce_pers_nopr[16] =
438  { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
439  0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
440 
441 unsigned char result_pr[16] =
442  { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
443  0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
444 
445 unsigned char result_nopr[16] =
446  { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
447  0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
448 
449 int test_offset;
450 int ctr_drbg_self_test_entropy( void *data, unsigned char *buf, size_t len )
451 {
452  unsigned char *p = data;
453  memcpy( buf, p + test_offset, len );
454  test_offset += 32;
455  return( 0 );
456 }
457 
458 /*
459  * Checkup routine
460  */
461 int ctr_drbg_self_test( int verbose )
462 {
463  ctr_drbg_context ctx;
464  unsigned char buf[16];
465 
466  /*
467  * Based on a NIST CTR_DRBG test vector (PR = True)
468  */
469  if( verbose != 0 )
470  printf( " CTR_DRBG (PR = TRUE) : " );
471 
472  test_offset = 0;
473  if( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy, entropy_source_pr, nonce_pers_pr, 16, 32 ) != 0 )
474  {
475  if( verbose != 0 )
476  printf( "failed\n" );
477 
478  return( 1 );
479  }
481 
482  if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 )
483  {
484  if( verbose != 0 )
485  printf( "failed\n" );
486 
487  return( 1 );
488  }
489 
490  if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 )
491  {
492  if( verbose != 0 )
493  printf( "failed\n" );
494 
495  return( 1 );
496  }
497 
498  if( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) != 0 )
499  {
500  if( verbose != 0 )
501  printf( "failed\n" );
502 
503  return( 1 );
504  }
505 
506  if( verbose != 0 )
507  printf( "passed\n" );
508 
509  /*
510  * Based on a NIST CTR_DRBG test vector (PR = FALSE)
511  */
512  if( verbose != 0 )
513  printf( " CTR_DRBG (PR = FALSE): " );
514 
515  test_offset = 0;
516  if( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy, entropy_source_nopr, nonce_pers_nopr, 16, 32 ) != 0 )
517  {
518  if( verbose != 0 )
519  printf( "failed\n" );
520 
521  return( 1 );
522  }
523 
524  if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
525  {
526  if( verbose != 0 )
527  printf( "failed\n" );
528 
529  return( 1 );
530  }
531 
532  if( ctr_drbg_reseed( &ctx, NULL, 0 ) != 0 )
533  {
534  if( verbose != 0 )
535  printf( "failed\n" );
536 
537  return( 1 );
538  }
539 
540  if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
541  {
542  if( verbose != 0 )
543  printf( "failed\n" );
544 
545  return( 1 );
546  }
547 
548  if( memcmp( buf, result_nopr, 16 ) != 0 )
549  {
550  if( verbose != 0 )
551  printf( "failed\n" );
552 
553  return( 1 );
554  }
555 
556  if( verbose != 0 )
557  printf( "passed\n" );
558 
559  if( verbose != 0 )
560  printf( "\n" );
561 
562  return( 0 );
563 }
564 #endif
565 
566 #endif