blob: e3796a077159b7908a7512a31dba8840faf7a9b7 [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,
Paul Bakker1bc9efc2011-12-03 11:29:32 +000040 const unsigned char *custom,
Paul Bakker0e04d0e2011-11-27 14:46:59 +000041 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
Paul Bakker1bc9efc2011-12-03 11:29:32 +000081int block_cipher_df( unsigned char *output,
82 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000083{
Paul Bakker2bc7cf12011-11-29 10:50:51 +000084 unsigned char buf[CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16];
Paul Bakker0e04d0e2011-11-27 14:46:59 +000085 unsigned char tmp[CTR_DRBG_SEEDLEN];
Paul Bakker2bc7cf12011-11-29 10:50:51 +000086 unsigned char key[CTR_DRBG_KEYSIZE];
87 unsigned char chain[CTR_DRBG_BLOCKSIZE];
88 unsigned char *p = buf, *iv;
Paul Bakker0e04d0e2011-11-27 14:46:59 +000089 aes_context aes_ctx;
90
91 int i, j, buf_len, use_len;
92
Paul Bakker2bc7cf12011-11-29 10:50:51 +000093 memset( buf, 0, CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16 );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000094
95 /*
96 * Construct IV (16 bytes) and S in buffer
97 * IV = Counter (in 32-bits) padded to 16 with zeroes
98 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
99 * data || 0x80
100 * (Total is padded to a multiple of 16-bytes with zeroes)
101 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000102 p = buf + CTR_DRBG_BLOCKSIZE;
103 *p++ = ( data_len >> 24 ) & 0xff;
104 *p++ = ( data_len >> 16 ) & 0xff;
105 *p++ = ( data_len >> 8 ) & 0xff;
106 *p++ = ( data_len ) & 0xff;
107 p += 3;
108 *p++ = CTR_DRBG_SEEDLEN;
109 memcpy( p, data, data_len );
110 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000111
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000112 buf_len = CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000113
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000114 for( i = 0; i < CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000115 key[i] = i;
116
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000117 aes_setkey_enc( &aes_ctx, key, CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000118
119 /*
120 * Reduce data to POLARSSL_CTR_DRBG_SEEDLEN bytes of data
121 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000122 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000123 {
124 p = buf;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000125 memset( chain, 0, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000126 use_len = buf_len;
127
128 while( use_len > 0 )
129 {
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000130 for( i = 0; i < CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000131 chain[i] ^= p[i];
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000132 p += CTR_DRBG_BLOCKSIZE;
133 use_len -= CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000134
135 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, chain, chain );
136 }
137
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000138 memcpy( tmp + j, chain, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000139
140 /*
141 * Update IV
142 */
143 buf[3]++;
144 }
145
146 /*
147 * Do final encryption with reduced data
148 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000149 aes_setkey_enc( &aes_ctx, tmp, CTR_DRBG_KEYBITS );
150 iv = tmp + CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000151 p = output;
152
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000153 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000154 {
155 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, iv, iv );
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000156 memcpy( p, iv, CTR_DRBG_BLOCKSIZE );
157 p += CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000158 }
159
160 return( 0 );
161}
162
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000163int ctr_drbg_update_internal( ctr_drbg_context *ctx,
164 const unsigned char data[CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000165{
166 unsigned char tmp[CTR_DRBG_SEEDLEN];
167 unsigned char *p = tmp;
168 int cb, i, j;
169
170 memset( tmp, 0, CTR_DRBG_SEEDLEN );
171
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000172 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000173 {
174 /*
175 * Increase counter
176 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000177 i = CTR_DRBG_BLOCKSIZE - 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000178 do {
179 ctx->counter[i]++;
180 cb = ctx->counter[i] == 0;
181 } while( i-- && cb );
182
183 /*
184 * Crypt counter block
185 */
186 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, p );
187
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000188 p += CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000189 }
190
191 for( i = 0; i < CTR_DRBG_SEEDLEN; i++ )
192 tmp[i] ^= data[i];
193
194 /*
195 * Update key and counter
196 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000197 aes_setkey_enc( &ctx->aes_ctx, tmp, CTR_DRBG_KEYBITS );
198 memcpy( ctx->counter, tmp + CTR_DRBG_KEYSIZE, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000199
200 return( 0 );
201}
202
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000203void ctr_drbg_update( ctr_drbg_context *ctx,
204 const unsigned char *additional, size_t add_len )
205{
206 unsigned char add_input[CTR_DRBG_SEEDLEN];
207
208 if( add_len > 0 )
209 {
210 block_cipher_df( add_input, additional, add_len );
211 ctr_drbg_update_internal( ctx, add_input );
212 }
213}
214
215int ctr_drbg_reseed( ctr_drbg_context *ctx,
216 const unsigned char *additional, size_t len )
217{
218 unsigned char seed[CTR_DRBG_MAX_SEED_INPUT];
219 size_t seedlen = 0;
220
221 if( ctx->entropy_len + len > CTR_DRBG_MAX_SEED_INPUT )
222 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
223
224 memset( seed, 0, CTR_DRBG_MAX_SEED_INPUT );
225
226 /*
227 * Gather POLARSSL_CTR_DRBG_ENTROPYLEN bytes of entropy to seed state
228 */
229 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
230 ctx->entropy_len ) )
231 {
232 return( POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
233 }
234
235 seedlen += ctx->entropy_len;
236
237 /*
238 * Add additional data
239 */
240 if( additional && len )
241 {
242 memcpy( seed + seedlen, additional, len );
243 seedlen += len;
244 }
245
246 /*
247 * Reduce to 384 bits
248 */
249 block_cipher_df( seed, seed, seedlen );
250
251 /*
252 * Update state
253 */
254 ctr_drbg_update_internal( ctx, seed );
255 ctx->reseed_counter = 1;
256
257 return( 0 );
258}
259
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000260int ctr_drbg_random_with_add( void *p_rng,
261 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000262 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000263{
264 int ret = 0;
265 ctr_drbg_context *ctx = (ctr_drbg_context *) p_rng;
266 unsigned char add_input[CTR_DRBG_SEEDLEN];
267 unsigned char *p = output;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000268 unsigned char tmp[CTR_DRBG_BLOCKSIZE];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000269 int cb, i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000270 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000271
272 if( output_len > CTR_DRBG_MAX_REQUEST )
273 return( POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG );
274
275 if( add_len > CTR_DRBG_MAX_INPUT )
276 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
277
278 memset( add_input, 0, CTR_DRBG_SEEDLEN );
279
280 if( ctx->reseed_counter > ctx->reseed_interval ||
281 ctx->prediction_resistance )
282 {
283 if( ( ret = ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
284 return( ret );
285
286 add_len = 0;
287 }
288
289 if( add_len > 0 )
290 {
291 block_cipher_df( add_input, additional, add_len );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000292 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000293 }
294
295 while( output_len > 0 )
296 {
297 /*
298 * Increase counter
299 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000300 i = CTR_DRBG_BLOCKSIZE - 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000301 do {
302 ctx->counter[i]++;
303 cb = ctx->counter[i] == 0;
304 } while( i-- && cb );
305
306 /*
307 * Crypt counter block
308 */
309 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, tmp );
310
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000311 use_len = (output_len > CTR_DRBG_BLOCKSIZE ) ? CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000312 /*
313 * Copy random block to destination
314 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000315 memcpy( p, tmp, use_len );
316 p += use_len;
317 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000318 }
319
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000320 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000321
322 ctx->reseed_counter++;
323
324 return( 0 );
325}
326
327int ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
328{
329 return ctr_drbg_random_with_add( p_rng, output, output_len, NULL, 0 );
330}
331
332#if defined(POLARSSL_SELF_TEST)
333
334#include <stdio.h>
335
336unsigned char entropy_source_pr[96] =
337 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
338 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
339 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
340 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
341 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
342 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
343 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
344 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
345 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
346 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
347 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
348 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
349
350unsigned char entropy_source_nopr[64] =
351 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
352 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
353 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
354 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
355 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
356 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
357 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
358 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
359
360unsigned char nonce_pers_pr[16] =
361 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
362 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
363
364unsigned char nonce_pers_nopr[16] =
365 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
366 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
367
368unsigned char result_pr[16] =
369 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
370 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
371
372unsigned char result_nopr[16] =
373 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
374 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
375
376int test_offset;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000377int ctr_drbg_self_test_entropy( void *data, unsigned char *buf, size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000378{
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000379 unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000380 memcpy( buf, p + test_offset, len );
381 test_offset += 32;
382 return( 0 );
383}
384
385/*
386 * Checkup routine
387 */
388int ctr_drbg_self_test( int verbose )
389{
390 ctr_drbg_context ctx;
391 unsigned char buf[16];
392
393 /*
394 * Based on a NIST CTR_DRBG test vector (PR = True)
395 */
396 if( verbose != 0 )
397 printf( " CTR_DRBG (PR = TRUE) : " );
398
399 test_offset = 0;
400 if( ctr_drbg_init( &ctx, ctr_drbg_self_test_entropy, entropy_source_pr, nonce_pers_pr, 16 ) != 0 )
401 {
402 if( verbose != 0 )
403 printf( "failed\n" );
404
405 return( 1 );
406 }
407 ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON );
408
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000409 if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000410 {
411 if( verbose != 0 )
412 printf( "failed\n" );
413
414 return( 1 );
415 }
416
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000417 if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000418 {
419 if( verbose != 0 )
420 printf( "failed\n" );
421
422 return( 1 );
423 }
424
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000425 if( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000426 {
427 if( verbose != 0 )
428 printf( "failed\n" );
429
430 return( 1 );
431 }
432
433 if( verbose != 0 )
434 printf( "passed\n" );
435
436 /*
437 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
438 */
439 if( verbose != 0 )
440 printf( " CTR_DRBG (PR = FALSE): " );
441
442 test_offset = 0;
443 if( ctr_drbg_init( &ctx, ctr_drbg_self_test_entropy, entropy_source_nopr, nonce_pers_nopr, 16 ) != 0 )
444 {
445 if( verbose != 0 )
446 printf( "failed\n" );
447
448 return( 1 );
449 }
450
451 if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
452 {
453 if( verbose != 0 )
454 printf( "failed\n" );
455
456 return( 1 );
457 }
458
459 if( ctr_drbg_reseed( &ctx, NULL, 0 ) != 0 )
460 {
461 if( verbose != 0 )
462 printf( "failed\n" );
463
464 return( 1 );
465 }
466
467 if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
468 {
469 if( verbose != 0 )
470 printf( "failed\n" );
471
472 return( 1 );
473 }
474
475 if( memcmp( buf, result_nopr, 16 ) != 0 )
476 {
477 if( verbose != 0 )
478 printf( "failed\n" );
479
480 return( 1 );
481 }
482
483 if( verbose != 0 )
484 printf( "passed\n" );
485
486 if( verbose != 0 )
487 printf( "\n" );
488
489 return( 0 );
490}
491#endif
492
493#endif