PolarSSL v1.3.9
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-2014, 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#if !defined(POLARSSL_CONFIG_FILE)
32#include "polarssl/config.h"
33#else
34#include POLARSSL_CONFIG_FILE
35#endif
36
37#if defined(POLARSSL_CTR_DRBG_C)
38
39#include "polarssl/ctr_drbg.h"
40
41#if defined(POLARSSL_FS_IO)
42#include <stdio.h>
43#endif
44
45#if defined(POLARSSL_PLATFORM_C)
46#include "polarssl/platform.h"
47#else
48#define polarssl_printf printf
49#endif
50
51/* 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
56/*
57 * Non-public function wrapped by ctr_crbg_init(). Necessary to allow NIST
58 * tests to succeed (which require known length fixed entropy)
59 */
62 int (*f_entropy)(void *, unsigned char *, size_t),
63 void *p_entropy,
64 const unsigned char *custom,
65 size_t len,
66 size_t entropy_len )
67{
68 int ret;
69 unsigned char key[CTR_DRBG_KEYSIZE];
70
71 memset( ctx, 0, sizeof(ctr_drbg_context) );
72 memset( key, 0, CTR_DRBG_KEYSIZE );
73
74 aes_init( &ctx->aes_ctx );
75
76 ctx->f_entropy = f_entropy;
77 ctx->p_entropy = p_entropy;
78
79 ctx->entropy_len = entropy_len;
81
82 /*
83 * Initialize with an empty key
84 */
86
87 if( ( ret = ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
88 return( ret );
89
90 return( 0 );
91}
92
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,
101}
102
104{
105 if( ctx == NULL )
106 return;
107
108 aes_free( &ctx->aes_ctx );
109 polarssl_zeroize( ctx, sizeof( ctr_drbg_context ) );
110}
111
112void 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}
121
122void ctr_drbg_set_reseed_interval( ctr_drbg_context *ctx, int interval )
123{
124 ctx->reseed_interval = interval;
125}
126
127static int block_cipher_df( unsigned char *output,
128 const unsigned char *data, size_t data_len )
129{
130 unsigned char buf[CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16];
131 unsigned char tmp[CTR_DRBG_SEEDLEN];
132 unsigned char key[CTR_DRBG_KEYSIZE];
133 unsigned char chain[CTR_DRBG_BLOCKSIZE];
134 unsigned char *p, *iv;
135 aes_context aes_ctx;
136
137 int i, j;
138 size_t buf_len, use_len;
139
140 memset( buf, 0, CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16 );
141 aes_init( &aes_ctx );
142
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 */
150 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;
159
160 buf_len = CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
161
162 for( i = 0; i < CTR_DRBG_KEYSIZE; i++ )
163 key[i] = i;
164
165 aes_setkey_enc( &aes_ctx, key, CTR_DRBG_KEYBITS );
166
167 /*
168 * Reduce data to POLARSSL_CTR_DRBG_SEEDLEN bytes of data
169 */
170 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
171 {
172 p = buf;
173 memset( chain, 0, CTR_DRBG_BLOCKSIZE );
174 use_len = buf_len;
175
176 while( use_len > 0 )
177 {
178 for( i = 0; i < CTR_DRBG_BLOCKSIZE; i++ )
179 chain[i] ^= p[i];
181 use_len -= ( use_len >= CTR_DRBG_BLOCKSIZE ) ?
182 CTR_DRBG_BLOCKSIZE : use_len;
183
184 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, chain, chain );
185 }
186
187 memcpy( tmp + j, chain, CTR_DRBG_BLOCKSIZE );
188
189 /*
190 * Update IV
191 */
192 buf[3]++;
193 }
194
195 /*
196 * Do final encryption with reduced data
197 */
198 aes_setkey_enc( &aes_ctx, tmp, CTR_DRBG_KEYBITS );
199 iv = tmp + CTR_DRBG_KEYSIZE;
200 p = output;
201
202 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
203 {
204 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, iv, iv );
205 memcpy( p, iv, CTR_DRBG_BLOCKSIZE );
207 }
208
209 aes_free( &aes_ctx );
210
211 return( 0 );
212}
213
214static int ctr_drbg_update_internal( ctr_drbg_context *ctx,
215 const unsigned char data[CTR_DRBG_SEEDLEN] )
216{
217 unsigned char tmp[CTR_DRBG_SEEDLEN];
218 unsigned char *p = tmp;
219 int i, j;
220
221 memset( tmp, 0, CTR_DRBG_SEEDLEN );
222
223 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
224 {
225 /*
226 * Increase counter
227 */
228 for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
229 if( ++ctx->counter[i - 1] != 0 )
230 break;
231
232 /*
233 * Crypt counter block
234 */
235 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, p );
236
238 }
239
240 for( i = 0; i < CTR_DRBG_SEEDLEN; i++ )
241 tmp[i] ^= data[i];
242
243 /*
244 * Update key and counter
245 */
247 memcpy( ctx->counter, tmp + CTR_DRBG_KEYSIZE, CTR_DRBG_BLOCKSIZE );
248
249 return( 0 );
250}
251
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 {
259 block_cipher_df( add_input, additional, add_len );
260 ctr_drbg_update_internal( ctx, add_input );
261 }
262}
263
265 const unsigned char *additional, size_t len )
266{
267 unsigned char seed[CTR_DRBG_MAX_SEED_INPUT];
268 size_t seedlen = 0;
269
270 if( ctx->entropy_len + len > CTR_DRBG_MAX_SEED_INPUT )
272
273 memset( seed, 0, CTR_DRBG_MAX_SEED_INPUT );
274
275 /*
276 * Gather entropy_len bytes of entropy to seed state
277 */
278 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
279 ctx->entropy_len ) )
280 {
282 }
283
284 seedlen += ctx->entropy_len;
285
286 /*
287 * Add additional data
288 */
289 if( additional && len )
290 {
291 memcpy( seed + seedlen, additional, len );
292 seedlen += len;
293 }
294
295 /*
296 * Reduce to 384 bits
297 */
298 block_cipher_df( seed, seed, seedlen );
299
300 /*
301 * Update state
302 */
303 ctr_drbg_update_internal( ctx, seed );
304 ctx->reseed_counter = 1;
305
306 return( 0 );
307}
308
309int ctr_drbg_random_with_add( void *p_rng,
310 unsigned char *output, size_t output_len,
311 const unsigned char *additional, size_t add_len )
312{
313 int ret = 0;
314 ctr_drbg_context *ctx = (ctr_drbg_context *) p_rng;
315 unsigned char add_input[CTR_DRBG_SEEDLEN];
316 unsigned char *p = output;
317 unsigned char tmp[CTR_DRBG_BLOCKSIZE];
318 int i;
319 size_t use_len;
320
321 if( output_len > CTR_DRBG_MAX_REQUEST )
323
324 if( add_len > CTR_DRBG_MAX_INPUT )
326
327 memset( add_input, 0, CTR_DRBG_SEEDLEN );
328
329 if( ctx->reseed_counter > ctx->reseed_interval ||
331 {
332 if( ( ret = ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
333 return( ret );
334
335 add_len = 0;
336 }
337
338 if( add_len > 0 )
339 {
340 block_cipher_df( add_input, additional, add_len );
341 ctr_drbg_update_internal( ctx, add_input );
342 }
343
344 while( output_len > 0 )
345 {
346 /*
347 * Increase counter
348 */
349 for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
350 if( ++ctx->counter[i - 1] != 0 )
351 break;
352
353 /*
354 * Crypt counter block
355 */
356 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, tmp );
357
358 use_len = ( output_len > CTR_DRBG_BLOCKSIZE ) ? CTR_DRBG_BLOCKSIZE :
359 output_len;
360 /*
361 * Copy random block to destination
362 */
363 memcpy( p, tmp, use_len );
364 p += use_len;
365 output_len -= use_len;
366 }
367
368 ctr_drbg_update_internal( ctx, add_input );
369
370 ctx->reseed_counter++;
371
372 return( 0 );
373}
374
375int ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
376{
377 return ctr_drbg_random_with_add( p_rng, output, output_len, NULL, 0 );
378}
379
380#if defined(POLARSSL_FS_IO)
381int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path )
382{
384 FILE *f;
385 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
386
387 if( ( f = fopen( path, "wb" ) ) == NULL )
389
390 if( ( ret = ctr_drbg_random( ctx, buf, CTR_DRBG_MAX_INPUT ) ) != 0 )
391 goto exit;
392
393 if( fwrite( buf, 1, CTR_DRBG_MAX_INPUT, f ) != CTR_DRBG_MAX_INPUT )
394 {
396 goto exit;
397 }
398
399 ret = 0;
400
401exit:
402 fclose( f );
403 return( ret );
404}
405
406int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path )
407{
408 FILE *f;
409 size_t n;
410 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
411
412 if( ( f = fopen( path, "rb" ) ) == NULL )
414
415 fseek( f, 0, SEEK_END );
416 n = (size_t) ftell( f );
417 fseek( f, 0, SEEK_SET );
418
419 if( n > CTR_DRBG_MAX_INPUT )
420 {
421 fclose( f );
423 }
424
425 if( fread( buf, 1, n, f ) != n )
426 {
427 fclose( f );
429 }
430
431 fclose( f );
432
433 ctr_drbg_update( ctx, buf, n );
434
435 return( ctr_drbg_write_seed_file( ctx, path ) );
436}
437#endif /* POLARSSL_FS_IO */
438
439#if defined(POLARSSL_SELF_TEST)
440
441#include <stdio.h>
442
443static unsigned char entropy_source_pr[96] =
444 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
445 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
446 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
447 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
448 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
449 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
450 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
451 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
452 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
453 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
454 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
455 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
456
457static unsigned char entropy_source_nopr[64] =
458 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
459 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
460 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
461 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
462 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
463 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
464 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
465 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
466
467static const unsigned char nonce_pers_pr[16] =
468 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
469 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
470
471static const unsigned char nonce_pers_nopr[16] =
472 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
473 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
474
475static const unsigned char result_pr[16] =
476 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
477 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
478
479static const unsigned char result_nopr[16] =
480 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
481 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
482
483static size_t test_offset;
484static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
485 size_t len )
486{
487 const unsigned char *p = data;
488 memcpy( buf, p + test_offset, len );
489 test_offset += len;
490 return( 0 );
491}
492
493#define CHK( c ) if( (c) != 0 ) \
494 { \
495 if( verbose != 0 ) \
496 polarssl_printf( "failed\n" ); \
497 return( 1 ); \
498 }
499
500/*
501 * Checkup routine
502 */
503int ctr_drbg_self_test( int verbose )
504{
506 unsigned char buf[16];
507
508 /*
509 * Based on a NIST CTR_DRBG test vector (PR = True)
510 */
511 if( verbose != 0 )
512 polarssl_printf( " CTR_DRBG (PR = TRUE) : " );
513
514 test_offset = 0;
515 CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
516 entropy_source_pr, nonce_pers_pr, 16, 32 ) );
518 CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) );
519 CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) );
520 CHK( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) );
521
522 if( verbose != 0 )
523 polarssl_printf( "passed\n" );
524
525 /*
526 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
527 */
528 if( verbose != 0 )
529 polarssl_printf( " CTR_DRBG (PR = FALSE): " );
530
531 test_offset = 0;
532 CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
533 entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
534 CHK( ctr_drbg_random( &ctx, buf, 16 ) );
535 CHK( ctr_drbg_reseed( &ctx, NULL, 0 ) );
536 CHK( ctr_drbg_random( &ctx, buf, 16 ) );
537 CHK( memcmp( buf, result_nopr, 16 ) );
538
539 if( verbose != 0 )
540 polarssl_printf( "passed\n" );
541
542 if( verbose != 0 )
543 polarssl_printf( "\n" );
544
545 return( 0 );
546}
547#endif /* POLARSSL_SELF_TEST */
548
549#endif /* POLARSSL_CTR_DRBG_C */
int aes_crypt_ecb(aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16])
AES-ECB block encryption/decryption.
int aes_setkey_enc(aes_context *ctx, const unsigned char *key, unsigned int keysize)
AES key schedule (encryption)
#define AES_ENCRYPT
Definition: aes.h:46
void aes_free(aes_context *ctx)
Clear AES context.
void aes_init(aes_context *ctx)
Initialize AES context.
Configuration options (set of defines)
CTR_DRBG based on AES-256 (NIST SP 800-90)
void ctr_drbg_set_prediction_resistance(ctr_drbg_context *ctx, int resistance)
Enable / disable prediction resistance (Default: Off)
int ctr_drbg_update_seed_file(ctr_drbg_context *ctx, const char *path)
Read and update a seed file.
int ctr_drbg_init(ctr_drbg_context *ctx, int(*f_entropy)(void *, unsigned char *, size_t), void *p_entropy, const unsigned char *custom, size_t len)
CTR_DRBG initialization.
int ctr_drbg_init_entropy_len(ctr_drbg_context *, int(*)(void *, unsigned char *, size_t), void *, const unsigned char *, size_t, size_t)
int ctr_drbg_write_seed_file(ctr_drbg_context *ctx, const char *path)
Write a seed file.
int ctr_drbg_random(void *p_rng, unsigned char *output, size_t output_len)
CTR_DRBG generate random.
#define POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED
The entropy source failed.
Definition: ctr_drbg.h:34
void ctr_drbg_set_reseed_interval(ctr_drbg_context *ctx, int interval)
Set the reseed interval (Default: CTR_DRBG_RESEED_INTERVAL)
void ctr_drbg_set_entropy_len(ctr_drbg_context *ctx, size_t len)
Set the amount of entropy grabbed on each (re)seed (Default: CTR_DRBG_ENTROPY_LEN)
#define POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG
Too many random requested in single call.
Definition: ctr_drbg.h:35
void ctr_drbg_update(ctr_drbg_context *ctx, const unsigned char *additional, size_t add_len)
CTR_DRBG update state.
int ctr_drbg_random_with_add(void *p_rng, unsigned char *output, size_t output_len, const unsigned char *additional, size_t add_len)
CTR_DRBG generate random with additional update input.
#define CTR_DRBG_KEYSIZE
Key size used by the cipher
Definition: ctr_drbg.h:40
#define CTR_DRBG_BLOCKSIZE
Block size used by the cipher
Definition: ctr_drbg.h:39
#define CTR_DRBG_MAX_REQUEST
Maximum number of requested bytes per call.
Definition: ctr_drbg.h:70
int ctr_drbg_self_test(int verbose)
Checkup routine.
#define CTR_DRBG_MAX_INPUT
Maximum number of additional input bytes.
Definition: ctr_drbg.h:66
#define CTR_DRBG_ENTROPY_LEN
Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256)
Definition: ctr_drbg.h:55
#define CTR_DRBG_RESEED_INTERVAL
Interval before reseed is performed by default.
Definition: ctr_drbg.h:62
#define CTR_DRBG_SEEDLEN
The seed length (counter + AES key)
Definition: ctr_drbg.h:42
#define POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR
Read/write error in file.
Definition: ctr_drbg.h:37
#define CTR_DRBG_PR_ON
Prediction resistance enabled
Definition: ctr_drbg.h:80
#define POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG
Input too large (Entropy + additional).
Definition: ctr_drbg.h:36
#define CTR_DRBG_KEYBITS
Definition: ctr_drbg.h:41
#define CTR_DRBG_MAX_SEED_INPUT
Maximum size of (re)seed buffer.
Definition: ctr_drbg.h:74
void ctr_drbg_free(ctr_drbg_context *ctx)
Clear CTR_CRBG context data.
int ctr_drbg_reseed(ctr_drbg_context *ctx, const unsigned char *additional, size_t len)
CTR_DRBG reseeding (extracts data from entropy source)
PolarSSL Platform abstraction layer.
AES context structure.
Definition: aes.h:69
CTR_DRBG context structure.
Definition: ctr_drbg.h:90
int(* f_entropy)(void *, unsigned char *, size_t)
Definition: ctr_drbg.h:104
size_t entropy_len
Definition: ctr_drbg.h:95
aes_context aes_ctx
Definition: ctr_drbg.h:99
int prediction_resistance
Definition: ctr_drbg.h:93
void * p_entropy
Definition: ctr_drbg.h:106
unsigned char counter[16]
Definition: ctr_drbg.h:91
int reseed_counter
Definition: ctr_drbg.h:92
int reseed_interval
Definition: ctr_drbg.h:97
#define polarssl_printf