blob: 3eab542a0fe5bce36334b0d18dbe642a80418092 [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;
44 unsigned char key[32];
45
46 memset( ctx, 0, sizeof(ctr_drbg_context) );
47 memset( key, 0, 32 );
48
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 */
58 aes_setkey_enc( &ctx->aes_ctx, key, 256 );
59
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{
83 unsigned char buf[CTR_DRBG_MAX_INPUT + 32];
84 unsigned char tmp[CTR_DRBG_SEEDLEN];
85 unsigned char key[32];
86 unsigned char chain[16];
87 unsigned char *p, *iv;
88 aes_context aes_ctx;
89
90 int i, j, buf_len, use_len;
91
92 memset( buf, 0, CTR_DRBG_MAX_INPUT + 32 );
93
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 */
101 buf[16] = ( data_len >> 24 ) & 0xff;
102 buf[17] = ( data_len >> 16 ) & 0xff;
103 buf[18] = ( data_len >> 8 ) & 0xff;
104 buf[19] = ( data_len ) & 0xff;
105 buf[23] = CTR_DRBG_SEEDLEN;
106 memcpy( buf + 24, data, data_len );
107 buf[24 + data_len] = 0x80;
108
109 buf_len = 24 + data_len + 1;
110
111 for( i = 0; i < 32; i++ )
112 key[i] = i;
113
114 aes_setkey_enc( &aes_ctx, key, 256 );
115
116 /*
117 * Reduce data to POLARSSL_CTR_DRBG_SEEDLEN bytes of data
118 */
119 for( j = 0; j < CTR_DRBG_SEEDLEN; j += 16 )
120 {
121 p = buf;
122 memset( chain, 0, 16 );
123 use_len = buf_len;
124
125 while( use_len > 0 )
126 {
127 for( i = 0; i < 16; i++ )
128 chain[i] ^= p[i];
129 p += 16;
130 use_len -= 16;
131
132 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, chain, chain );
133 }
134
135 memcpy( tmp + j, chain, 16 );
136
137 /*
138 * Update IV
139 */
140 buf[3]++;
141 }
142
143 /*
144 * Do final encryption with reduced data
145 */
146 aes_setkey_enc( &aes_ctx, tmp, 256 );
147 iv = tmp + 32;
148 p = output;
149
150 for( j = 0; j < CTR_DRBG_SEEDLEN; j += 16 )
151 {
152 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, iv, iv );
153 memcpy( p, iv, 16 );
154 p += 16;
155 }
156
157 return( 0 );
158}
159
160int ctr_drbg_reseed( ctr_drbg_context *ctx, unsigned char *additional, size_t len )
161{
162 unsigned char seed[CTR_DRBG_MAX_SEED_INPUT];
163 size_t seedlen = 0;
164
165 if( ctx->entropy_len + len > CTR_DRBG_MAX_INPUT )
166 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
167
168 memset( seed, 0, CTR_DRBG_MAX_SEED_INPUT );
169
170 /*
171 * Gather POLARSSL_CTR_DRBG_ENTROPYLEN bytes of entropy to seed state
172 */
173 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
174 ctx->entropy_len ) )
175 {
176 return( POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
177 }
178
179 seedlen += ctx->entropy_len;
180
181 /*
182 * Add additional data
183 */
184 if( additional && len )
185 {
186 memcpy( seed + seedlen, additional, len );
187 seedlen += len;
188 }
189
190 /*
191 * Reduce to 384 bits
192 */
193 block_cipher_df( seed, seed, seedlen );
194
195 /*
196 * Update state
197 */
198 ctr_drbg_update( ctx, seed );
199 ctx->reseed_counter = 1;
200
201 return( 0 );
202}
203
204int ctr_drbg_update( ctr_drbg_context *ctx,
205 unsigned char data[CTR_DRBG_SEEDLEN] )
206{
207 unsigned char tmp[CTR_DRBG_SEEDLEN];
208 unsigned char *p = tmp;
209 int cb, i, j;
210
211 memset( tmp, 0, CTR_DRBG_SEEDLEN );
212
213 for( j = 0; j < CTR_DRBG_SEEDLEN; j += 16 )
214 {
215 /*
216 * Increase counter
217 */
218 i = 15;
219 do {
220 ctx->counter[i]++;
221 cb = ctx->counter[i] == 0;
222 } while( i-- && cb );
223
224 /*
225 * Crypt counter block
226 */
227 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, p );
228
229 p += 16;
230 }
231
232 for( i = 0; i < CTR_DRBG_SEEDLEN; i++ )
233 tmp[i] ^= data[i];
234
235 /*
236 * Update key and counter
237 */
238 aes_setkey_enc( &ctx->aes_ctx, tmp, 256 );
239 memcpy( ctx->counter, tmp + 32, 16 );
240
241 return( 0 );
242}
243
244int ctr_drbg_random_with_add( void *p_rng,
245 unsigned char *output, size_t output_len,
246 unsigned char *additional, size_t add_len )
247{
248 int ret = 0;
249 ctr_drbg_context *ctx = (ctr_drbg_context *) p_rng;
250 unsigned char add_input[CTR_DRBG_SEEDLEN];
251 unsigned char *p = output;
252 unsigned char tmp[16];
253 int cb, i;
254
255 if( output_len > CTR_DRBG_MAX_REQUEST )
256 return( POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG );
257
258 if( add_len > CTR_DRBG_MAX_INPUT )
259 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
260
261 memset( add_input, 0, CTR_DRBG_SEEDLEN );
262
263 if( ctx->reseed_counter > ctx->reseed_interval ||
264 ctx->prediction_resistance )
265 {
266 if( ( ret = ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
267 return( ret );
268
269 add_len = 0;
270 }
271
272 if( add_len > 0 )
273 {
274 block_cipher_df( add_input, additional, add_len );
275 ctr_drbg_update( ctx, add_input );
276 }
277
278 while( output_len > 0 )
279 {
280 /*
281 * Increase counter
282 */
283 i = 15;
284 do {
285 ctx->counter[i]++;
286 cb = ctx->counter[i] == 0;
287 } while( i-- && cb );
288
289 /*
290 * Crypt counter block
291 */
292 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, tmp );
293
294 /*
295 * Copy random block to destination
296 */
297 memcpy( p, tmp, (output_len > 16 ) ? 16 : output_len );
298 p += 16;
299 output_len -= 16;
300 }
301
302 ctr_drbg_update( ctx, add_input );
303
304 ctx->reseed_counter++;
305
306 return( 0 );
307}
308
309int ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
310{
311 return ctr_drbg_random_with_add( p_rng, output, output_len, NULL, 0 );
312}
313
314#if defined(POLARSSL_SELF_TEST)
315
316#include <stdio.h>
317
318unsigned char entropy_source_pr[96] =
319 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
320 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
321 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
322 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
323 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
324 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
325 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
326 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
327 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
328 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
329 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
330 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
331
332unsigned char entropy_source_nopr[64] =
333 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
334 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
335 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
336 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
337 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
338 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
339 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
340 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
341
342unsigned char nonce_pers_pr[16] =
343 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
344 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
345
346unsigned char nonce_pers_nopr[16] =
347 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
348 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
349
350unsigned char result_pr[16] =
351 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
352 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
353
354unsigned char result_nopr[16] =
355 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
356 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
357
358int test_offset;
359int ctr_drbg_self_test_entropy( void *p, unsigned char *buf, size_t len )
360{
361 memcpy( buf, p + test_offset, len );
362 test_offset += 32;
363 return( 0 );
364}
365
366/*
367 * Checkup routine
368 */
369int ctr_drbg_self_test( int verbose )
370{
371 ctr_drbg_context ctx;
372 unsigned char buf[16];
373
374 /*
375 * Based on a NIST CTR_DRBG test vector (PR = True)
376 */
377 if( verbose != 0 )
378 printf( " CTR_DRBG (PR = TRUE) : " );
379
380 test_offset = 0;
381 if( ctr_drbg_init( &ctx, ctr_drbg_self_test_entropy, entropy_source_pr, nonce_pers_pr, 16 ) != 0 )
382 {
383 if( verbose != 0 )
384 printf( "failed\n" );
385
386 return( 1 );
387 }
388 ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON );
389
390 if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
391 {
392 if( verbose != 0 )
393 printf( "failed\n" );
394
395 return( 1 );
396 }
397
398 if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
399 {
400 if( verbose != 0 )
401 printf( "failed\n" );
402
403 return( 1 );
404 }
405
406 if( memcmp( buf, result_pr, 16 ) != 0 )
407 {
408 if( verbose != 0 )
409 printf( "failed\n" );
410
411 return( 1 );
412 }
413
414 if( verbose != 0 )
415 printf( "passed\n" );
416
417 /*
418 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
419 */
420 if( verbose != 0 )
421 printf( " CTR_DRBG (PR = FALSE): " );
422
423 test_offset = 0;
424 if( ctr_drbg_init( &ctx, ctr_drbg_self_test_entropy, entropy_source_nopr, nonce_pers_nopr, 16 ) != 0 )
425 {
426 if( verbose != 0 )
427 printf( "failed\n" );
428
429 return( 1 );
430 }
431
432 if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
433 {
434 if( verbose != 0 )
435 printf( "failed\n" );
436
437 return( 1 );
438 }
439
440 if( ctr_drbg_reseed( &ctx, NULL, 0 ) != 0 )
441 {
442 if( verbose != 0 )
443 printf( "failed\n" );
444
445 return( 1 );
446 }
447
448 if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
449 {
450 if( verbose != 0 )
451 printf( "failed\n" );
452
453 return( 1 );
454 }
455
456 if( memcmp( buf, result_nopr, 16 ) != 0 )
457 {
458 if( verbose != 0 )
459 printf( "failed\n" );
460
461 return( 1 );
462 }
463
464 if( verbose != 0 )
465 printf( "passed\n" );
466
467 if( verbose != 0 )
468 printf( "\n" );
469
470 return( 0 );
471}
472#endif
473
474#endif