blob: d60770393e8146f7b50bf2b6c95adb465ebd3075 [file] [log] [blame]
Paul Bakker0e04d0e2011-11-27 14:46:59 +00001/*
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
37int ctr_drbg_init( ctr_drbg_context *ctx,
38 int (*f_entropy)(void *, unsigned char *, size_t),
39 void *p_entropy,
40 unsigned char *custom,
41 size_t len )
42{
43 int ret;
Paul Bakker2bc7cf12011-11-29 10:50:51 +000044 unsigned char key[CTR_DRBG_KEYSIZE];
Paul Bakker0e04d0e2011-11-27 14:46:59 +000045
46 memset( ctx, 0, sizeof(ctr_drbg_context) );
Paul Bakker2bc7cf12011-11-29 10:50:51 +000047 memset( key, 0, CTR_DRBG_KEYSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000048
49 ctx->f_entropy = f_entropy;
50 ctx->p_entropy = p_entropy;
51
52 ctx->entropy_len = CTR_DRBG_ENTROPY_LEN;
53 ctx->reseed_interval = CTR_DRBG_RESEED_INTERVAL;
54
55 /*
56 * Initialize with an empty key
57 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +000058 aes_setkey_enc( &ctx->aes_ctx, key, CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000059
60 if( ( ret = ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
61 return( ret );
62
63 return( 0 );
64}
65
66void ctr_drbg_set_prediction_resistance( ctr_drbg_context *ctx, int resistance )
67{
68 ctx->prediction_resistance = resistance;
69}
70
71void ctr_drbg_set_entropy_len( ctr_drbg_context *ctx, size_t len )
72{
73 ctx->entropy_len = len;
74}
75
76void ctr_drbg_set_reseed_interval( ctr_drbg_context *ctx, int interval )
77{
78 ctx->reseed_interval = interval;
79}
80
81int block_cipher_df( unsigned char *output, unsigned char *data, size_t data_len )
82{
Paul Bakker2bc7cf12011-11-29 10:50:51 +000083 unsigned char buf[CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16];
Paul Bakker0e04d0e2011-11-27 14:46:59 +000084 unsigned char tmp[CTR_DRBG_SEEDLEN];
Paul Bakker2bc7cf12011-11-29 10:50:51 +000085 unsigned char key[CTR_DRBG_KEYSIZE];
86 unsigned char chain[CTR_DRBG_BLOCKSIZE];
87 unsigned char *p = buf, *iv;
Paul Bakker0e04d0e2011-11-27 14:46:59 +000088 aes_context aes_ctx;
89
90 int i, j, buf_len, use_len;
91
Paul Bakker2bc7cf12011-11-29 10:50:51 +000092 memset( buf, 0, CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16 );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000093
94 /*
95 * Construct IV (16 bytes) and S in buffer
96 * IV = Counter (in 32-bits) padded to 16 with zeroes
97 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
98 * data || 0x80
99 * (Total is padded to a multiple of 16-bytes with zeroes)
100 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000101 p = buf + CTR_DRBG_BLOCKSIZE;
102 *p++ = ( data_len >> 24 ) & 0xff;
103 *p++ = ( data_len >> 16 ) & 0xff;
104 *p++ = ( data_len >> 8 ) & 0xff;
105 *p++ = ( data_len ) & 0xff;
106 p += 3;
107 *p++ = CTR_DRBG_SEEDLEN;
108 memcpy( p, data, data_len );
109 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000110
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000111 buf_len = CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000112
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000113 for( i = 0; i < CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000114 key[i] = i;
115
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000116 aes_setkey_enc( &aes_ctx, key, CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000117
118 /*
119 * Reduce data to POLARSSL_CTR_DRBG_SEEDLEN bytes of data
120 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000121 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000122 {
123 p = buf;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000124 memset( chain, 0, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000125 use_len = buf_len;
126
127 while( use_len > 0 )
128 {
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000129 for( i = 0; i < CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000130 chain[i] ^= p[i];
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000131 p += CTR_DRBG_BLOCKSIZE;
132 use_len -= CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000133
134 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, chain, chain );
135 }
136
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000137 memcpy( tmp + j, chain, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000138
139 /*
140 * Update IV
141 */
142 buf[3]++;
143 }
144
145 /*
146 * Do final encryption with reduced data
147 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000148 aes_setkey_enc( &aes_ctx, tmp, CTR_DRBG_KEYBITS );
149 iv = tmp + CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000150 p = output;
151
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000152 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000153 {
154 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, iv, iv );
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000155 memcpy( p, iv, CTR_DRBG_BLOCKSIZE );
156 p += CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000157 }
158
159 return( 0 );
160}
161
162int ctr_drbg_reseed( ctr_drbg_context *ctx, unsigned char *additional, size_t len )
163{
164 unsigned char seed[CTR_DRBG_MAX_SEED_INPUT];
165 size_t seedlen = 0;
166
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000167 if( ctx->entropy_len + len > CTR_DRBG_MAX_SEED_INPUT )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000168 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
169
170 memset( seed, 0, CTR_DRBG_MAX_SEED_INPUT );
171
172 /*
173 * Gather POLARSSL_CTR_DRBG_ENTROPYLEN bytes of entropy to seed state
174 */
175 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
176 ctx->entropy_len ) )
177 {
178 return( POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
179 }
180
181 seedlen += ctx->entropy_len;
182
183 /*
184 * Add additional data
185 */
186 if( additional && len )
187 {
188 memcpy( seed + seedlen, additional, len );
189 seedlen += len;
190 }
191
192 /*
193 * Reduce to 384 bits
194 */
195 block_cipher_df( seed, seed, seedlen );
196
197 /*
198 * Update state
199 */
200 ctr_drbg_update( ctx, seed );
201 ctx->reseed_counter = 1;
202
203 return( 0 );
204}
205
206int ctr_drbg_update( ctr_drbg_context *ctx,
207 unsigned char data[CTR_DRBG_SEEDLEN] )
208{
209 unsigned char tmp[CTR_DRBG_SEEDLEN];
210 unsigned char *p = tmp;
211 int cb, i, j;
212
213 memset( tmp, 0, CTR_DRBG_SEEDLEN );
214
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000215 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000216 {
217 /*
218 * Increase counter
219 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000220 i = CTR_DRBG_BLOCKSIZE - 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000221 do {
222 ctx->counter[i]++;
223 cb = ctx->counter[i] == 0;
224 } while( i-- && cb );
225
226 /*
227 * Crypt counter block
228 */
229 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, p );
230
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000231 p += CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000232 }
233
234 for( i = 0; i < CTR_DRBG_SEEDLEN; i++ )
235 tmp[i] ^= data[i];
236
237 /*
238 * Update key and counter
239 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000240 aes_setkey_enc( &ctx->aes_ctx, tmp, CTR_DRBG_KEYBITS );
241 memcpy( ctx->counter, tmp + CTR_DRBG_KEYSIZE, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000242
243 return( 0 );
244}
245
246int ctr_drbg_random_with_add( void *p_rng,
247 unsigned char *output, size_t output_len,
248 unsigned char *additional, size_t add_len )
249{
250 int ret = 0;
251 ctr_drbg_context *ctx = (ctr_drbg_context *) p_rng;
252 unsigned char add_input[CTR_DRBG_SEEDLEN];
253 unsigned char *p = output;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000254 unsigned char tmp[CTR_DRBG_BLOCKSIZE];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000255 int cb, i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000256 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000257
258 if( output_len > CTR_DRBG_MAX_REQUEST )
259 return( POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG );
260
261 if( add_len > CTR_DRBG_MAX_INPUT )
262 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
263
264 memset( add_input, 0, CTR_DRBG_SEEDLEN );
265
266 if( ctx->reseed_counter > ctx->reseed_interval ||
267 ctx->prediction_resistance )
268 {
269 if( ( ret = ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
270 return( ret );
271
272 add_len = 0;
273 }
274
275 if( add_len > 0 )
276 {
277 block_cipher_df( add_input, additional, add_len );
278 ctr_drbg_update( ctx, add_input );
279 }
280
281 while( output_len > 0 )
282 {
283 /*
284 * Increase counter
285 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000286 i = CTR_DRBG_BLOCKSIZE - 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000287 do {
288 ctx->counter[i]++;
289 cb = ctx->counter[i] == 0;
290 } while( i-- && cb );
291
292 /*
293 * Crypt counter block
294 */
295 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, tmp );
296
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000297 use_len = (output_len > CTR_DRBG_BLOCKSIZE ) ? CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000298 /*
299 * Copy random block to destination
300 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000301 memcpy( p, tmp, use_len );
302 p += use_len;
303 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000304 }
305
306 ctr_drbg_update( ctx, add_input );
307
308 ctx->reseed_counter++;
309
310 return( 0 );
311}
312
313int ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
314{
315 return ctr_drbg_random_with_add( p_rng, output, output_len, NULL, 0 );
316}
317
318#if defined(POLARSSL_SELF_TEST)
319
320#include <stdio.h>
321
322unsigned char entropy_source_pr[96] =
323 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
324 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
325 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
326 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
327 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
328 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
329 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
330 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
331 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
332 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
333 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
334 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
335
336unsigned char entropy_source_nopr[64] =
337 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
338 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
339 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
340 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
341 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
342 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
343 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
344 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
345
346unsigned char nonce_pers_pr[16] =
347 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
348 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
349
350unsigned char nonce_pers_nopr[16] =
351 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
352 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
353
354unsigned char result_pr[16] =
355 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
356 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
357
358unsigned char result_nopr[16] =
359 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
360 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
361
362int test_offset;
363int ctr_drbg_self_test_entropy( void *p, unsigned char *buf, size_t len )
364{
365 memcpy( buf, p + test_offset, len );
366 test_offset += 32;
367 return( 0 );
368}
369
370/*
371 * Checkup routine
372 */
373int ctr_drbg_self_test( int verbose )
374{
375 ctr_drbg_context ctx;
376 unsigned char buf[16];
377
378 /*
379 * Based on a NIST CTR_DRBG test vector (PR = True)
380 */
381 if( verbose != 0 )
382 printf( " CTR_DRBG (PR = TRUE) : " );
383
384 test_offset = 0;
385 if( ctr_drbg_init( &ctx, ctr_drbg_self_test_entropy, entropy_source_pr, nonce_pers_pr, 16 ) != 0 )
386 {
387 if( verbose != 0 )
388 printf( "failed\n" );
389
390 return( 1 );
391 }
392 ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON );
393
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000394 if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000395 {
396 if( verbose != 0 )
397 printf( "failed\n" );
398
399 return( 1 );
400 }
401
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000402 if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000403 {
404 if( verbose != 0 )
405 printf( "failed\n" );
406
407 return( 1 );
408 }
409
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000410 if( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000411 {
412 if( verbose != 0 )
413 printf( "failed\n" );
414
415 return( 1 );
416 }
417
418 if( verbose != 0 )
419 printf( "passed\n" );
420
421 /*
422 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
423 */
424 if( verbose != 0 )
425 printf( " CTR_DRBG (PR = FALSE): " );
426
427 test_offset = 0;
428 if( ctr_drbg_init( &ctx, ctr_drbg_self_test_entropy, entropy_source_nopr, nonce_pers_nopr, 16 ) != 0 )
429 {
430 if( verbose != 0 )
431 printf( "failed\n" );
432
433 return( 1 );
434 }
435
436 if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
437 {
438 if( verbose != 0 )
439 printf( "failed\n" );
440
441 return( 1 );
442 }
443
444 if( ctr_drbg_reseed( &ctx, NULL, 0 ) != 0 )
445 {
446 if( verbose != 0 )
447 printf( "failed\n" );
448
449 return( 1 );
450 }
451
452 if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
453 {
454 if( verbose != 0 )
455 printf( "failed\n" );
456
457 return( 1 );
458 }
459
460 if( memcmp( buf, result_nopr, 16 ) != 0 )
461 {
462 if( verbose != 0 )
463 printf( "failed\n" );
464
465 return( 1 );
466 }
467
468 if( verbose != 0 )
469 printf( "passed\n" );
470
471 if( verbose != 0 )
472 printf( "\n" );
473
474 return( 0 );
475}
476#endif
477
478#endif