blob: cc295c73fb4fdee0f58f827c296617f299552e8f [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;
256
257 if( output_len > CTR_DRBG_MAX_REQUEST )
258 return( POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG );
259
260 if( add_len > CTR_DRBG_MAX_INPUT )
261 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
262
263 memset( add_input, 0, CTR_DRBG_SEEDLEN );
264
265 if( ctx->reseed_counter > ctx->reseed_interval ||
266 ctx->prediction_resistance )
267 {
268 if( ( ret = ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
269 return( ret );
270
271 add_len = 0;
272 }
273
274 if( add_len > 0 )
275 {
276 block_cipher_df( add_input, additional, add_len );
277 ctr_drbg_update( ctx, add_input );
278 }
279
280 while( output_len > 0 )
281 {
282 /*
283 * Increase counter
284 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000285 i = CTR_DRBG_BLOCKSIZE - 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000286 do {
287 ctx->counter[i]++;
288 cb = ctx->counter[i] == 0;
289 } while( i-- && cb );
290
291 /*
292 * Crypt counter block
293 */
294 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, tmp );
295
296 /*
297 * Copy random block to destination
298 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000299 memcpy( p, tmp, (output_len > CTR_DRBG_BLOCKSIZE ) ? CTR_DRBG_BLOCKSIZE : output_len );
300 p += CTR_DRBG_BLOCKSIZE;
301 output_len -= CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000302 }
303
304 ctr_drbg_update( ctx, add_input );
305
306 ctx->reseed_counter++;
307
308 return( 0 );
309}
310
311int ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
312{
313 return ctr_drbg_random_with_add( p_rng, output, output_len, NULL, 0 );
314}
315
316#if defined(POLARSSL_SELF_TEST)
317
318#include <stdio.h>
319
320unsigned char entropy_source_pr[96] =
321 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
322 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
323 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
324 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
325 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
326 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
327 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
328 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
329 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
330 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
331 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
332 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
333
334unsigned char entropy_source_nopr[64] =
335 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
336 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
337 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
338 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
339 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
340 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
341 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
342 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
343
344unsigned char nonce_pers_pr[16] =
345 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
346 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
347
348unsigned char nonce_pers_nopr[16] =
349 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
350 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
351
352unsigned char result_pr[16] =
353 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
354 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
355
356unsigned char result_nopr[16] =
357 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
358 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
359
360int test_offset;
361int ctr_drbg_self_test_entropy( void *p, unsigned char *buf, size_t len )
362{
363 memcpy( buf, p + test_offset, len );
364 test_offset += 32;
365 return( 0 );
366}
367
368/*
369 * Checkup routine
370 */
371int ctr_drbg_self_test( int verbose )
372{
373 ctr_drbg_context ctx;
374 unsigned char buf[16];
375
376 /*
377 * Based on a NIST CTR_DRBG test vector (PR = True)
378 */
379 if( verbose != 0 )
380 printf( " CTR_DRBG (PR = TRUE) : " );
381
382 test_offset = 0;
383 if( ctr_drbg_init( &ctx, ctr_drbg_self_test_entropy, entropy_source_pr, nonce_pers_pr, 16 ) != 0 )
384 {
385 if( verbose != 0 )
386 printf( "failed\n" );
387
388 return( 1 );
389 }
390 ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON );
391
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000392 if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000393 {
394 if( verbose != 0 )
395 printf( "failed\n" );
396
397 return( 1 );
398 }
399
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000400 if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000401 {
402 if( verbose != 0 )
403 printf( "failed\n" );
404
405 return( 1 );
406 }
407
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000408 if( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000409 {
410 if( verbose != 0 )
411 printf( "failed\n" );
412
413 return( 1 );
414 }
415
416 if( verbose != 0 )
417 printf( "passed\n" );
418
419 /*
420 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
421 */
422 if( verbose != 0 )
423 printf( " CTR_DRBG (PR = FALSE): " );
424
425 test_offset = 0;
426 if( ctr_drbg_init( &ctx, ctr_drbg_self_test_entropy, entropy_source_nopr, nonce_pers_nopr, 16 ) != 0 )
427 {
428 if( verbose != 0 )
429 printf( "failed\n" );
430
431 return( 1 );
432 }
433
434 if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
435 {
436 if( verbose != 0 )
437 printf( "failed\n" );
438
439 return( 1 );
440 }
441
442 if( ctr_drbg_reseed( &ctx, NULL, 0 ) != 0 )
443 {
444 if( verbose != 0 )
445 printf( "failed\n" );
446
447 return( 1 );
448 }
449
450 if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
451 {
452 if( verbose != 0 )
453 printf( "failed\n" );
454
455 return( 1 );
456 }
457
458 if( memcmp( buf, result_nopr, 16 ) != 0 )
459 {
460 if( verbose != 0 )
461 printf( "failed\n" );
462
463 return( 1 );
464 }
465
466 if( verbose != 0 )
467 printf( "passed\n" );
468
469 if( verbose != 0 )
470 printf( "\n" );
471
472 return( 0 );
473}
474#endif
475
476#endif