blob: 8cf03712e00fcf45cc1948d09e75b7b3a72161fc [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
Paul Bakkerfc754a92011-12-05 13:23:51 +000037#if defined(POLARSSL_FS_IO)
38#include <stdio.h>
39#endif
40
Paul Bakker18d32912011-12-10 21:42:49 +000041/*
42 * Non-public function wrapped by ctr_crbg_init(). Necessary to allow NIST
43 * tests to succeed (which require known length fixed entropy)
44 */
45int ctr_drbg_init_entropy_len(
46 ctr_drbg_context *ctx,
Paul Bakker0e04d0e2011-11-27 14:46:59 +000047 int (*f_entropy)(void *, unsigned char *, size_t),
48 void *p_entropy,
Paul Bakker1bc9efc2011-12-03 11:29:32 +000049 const unsigned char *custom,
Paul Bakker18d32912011-12-10 21:42:49 +000050 size_t len,
51 size_t entropy_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000052{
53 int ret;
Paul Bakker2bc7cf12011-11-29 10:50:51 +000054 unsigned char key[CTR_DRBG_KEYSIZE];
Paul Bakker0e04d0e2011-11-27 14:46:59 +000055
56 memset( ctx, 0, sizeof(ctr_drbg_context) );
Paul Bakker2bc7cf12011-11-29 10:50:51 +000057 memset( key, 0, CTR_DRBG_KEYSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000058
59 ctx->f_entropy = f_entropy;
60 ctx->p_entropy = p_entropy;
61
Paul Bakker18d32912011-12-10 21:42:49 +000062 ctx->entropy_len = entropy_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +000063 ctx->reseed_interval = CTR_DRBG_RESEED_INTERVAL;
64
65 /*
66 * Initialize with an empty key
67 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +000068 aes_setkey_enc( &ctx->aes_ctx, key, CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000069
70 if( ( ret = ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
71 return( ret );
72
73 return( 0 );
74}
75
Paul Bakker18d32912011-12-10 21:42:49 +000076int ctr_drbg_init( ctr_drbg_context *ctx,
77 int (*f_entropy)(void *, unsigned char *, size_t),
78 void *p_entropy,
79 const unsigned char *custom,
80 size_t len )
81{
82 return( ctr_drbg_init_entropy_len( ctx, f_entropy, p_entropy, custom, len,
83 CTR_DRBG_ENTROPY_LEN ) );
84}
85
Paul Bakker0e04d0e2011-11-27 14:46:59 +000086void ctr_drbg_set_prediction_resistance( ctr_drbg_context *ctx, int resistance )
87{
88 ctx->prediction_resistance = resistance;
89}
90
91void ctr_drbg_set_entropy_len( ctr_drbg_context *ctx, size_t len )
92{
93 ctx->entropy_len = len;
94}
95
96void ctr_drbg_set_reseed_interval( ctr_drbg_context *ctx, int interval )
97{
98 ctx->reseed_interval = interval;
99}
100
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000101int block_cipher_df( unsigned char *output,
102 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000103{
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000104 unsigned char buf[CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000105 unsigned char tmp[CTR_DRBG_SEEDLEN];
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000106 unsigned char key[CTR_DRBG_KEYSIZE];
107 unsigned char chain[CTR_DRBG_BLOCKSIZE];
108 unsigned char *p = buf, *iv;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000109 aes_context aes_ctx;
110
111 int i, j, buf_len, use_len;
112
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000113 memset( buf, 0, CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16 );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000114
115 /*
116 * Construct IV (16 bytes) and S in buffer
117 * IV = Counter (in 32-bits) padded to 16 with zeroes
118 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
119 * data || 0x80
120 * (Total is padded to a multiple of 16-bytes with zeroes)
121 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000122 p = buf + CTR_DRBG_BLOCKSIZE;
123 *p++ = ( data_len >> 24 ) & 0xff;
124 *p++ = ( data_len >> 16 ) & 0xff;
125 *p++ = ( data_len >> 8 ) & 0xff;
126 *p++ = ( data_len ) & 0xff;
127 p += 3;
128 *p++ = CTR_DRBG_SEEDLEN;
129 memcpy( p, data, data_len );
130 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000131
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000132 buf_len = CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000133
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000134 for( i = 0; i < CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000135 key[i] = i;
136
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000137 aes_setkey_enc( &aes_ctx, key, CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000138
139 /*
140 * Reduce data to POLARSSL_CTR_DRBG_SEEDLEN bytes of data
141 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000142 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000143 {
144 p = buf;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000145 memset( chain, 0, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000146 use_len = buf_len;
147
148 while( use_len > 0 )
149 {
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000150 for( i = 0; i < CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000151 chain[i] ^= p[i];
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000152 p += CTR_DRBG_BLOCKSIZE;
153 use_len -= CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000154
155 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, chain, chain );
156 }
157
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000158 memcpy( tmp + j, chain, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000159
160 /*
161 * Update IV
162 */
163 buf[3]++;
164 }
165
166 /*
167 * Do final encryption with reduced data
168 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000169 aes_setkey_enc( &aes_ctx, tmp, CTR_DRBG_KEYBITS );
170 iv = tmp + CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000171 p = output;
172
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000173 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000174 {
175 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, iv, iv );
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000176 memcpy( p, iv, CTR_DRBG_BLOCKSIZE );
177 p += CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000178 }
179
180 return( 0 );
181}
182
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000183int ctr_drbg_update_internal( ctr_drbg_context *ctx,
184 const unsigned char data[CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000185{
186 unsigned char tmp[CTR_DRBG_SEEDLEN];
187 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000188 int i, j;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000189
190 memset( tmp, 0, CTR_DRBG_SEEDLEN );
191
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000192 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000193 {
194 /*
195 * Increase counter
196 */
Paul Bakker9a736322012-11-14 12:39:52 +0000197 for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000198 if( ++ctx->counter[i - 1] != 0 )
199 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000200
201 /*
202 * Crypt counter block
203 */
204 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, p );
205
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000206 p += CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000207 }
208
209 for( i = 0; i < CTR_DRBG_SEEDLEN; i++ )
210 tmp[i] ^= data[i];
211
212 /*
213 * Update key and counter
214 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000215 aes_setkey_enc( &ctx->aes_ctx, tmp, CTR_DRBG_KEYBITS );
216 memcpy( ctx->counter, tmp + CTR_DRBG_KEYSIZE, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000217
218 return( 0 );
219}
220
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000221void ctr_drbg_update( ctr_drbg_context *ctx,
222 const unsigned char *additional, size_t add_len )
223{
224 unsigned char add_input[CTR_DRBG_SEEDLEN];
225
226 if( add_len > 0 )
227 {
228 block_cipher_df( add_input, additional, add_len );
229 ctr_drbg_update_internal( ctx, add_input );
230 }
231}
232
233int ctr_drbg_reseed( ctr_drbg_context *ctx,
234 const unsigned char *additional, size_t len )
235{
236 unsigned char seed[CTR_DRBG_MAX_SEED_INPUT];
237 size_t seedlen = 0;
238
239 if( ctx->entropy_len + len > CTR_DRBG_MAX_SEED_INPUT )
240 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
241
242 memset( seed, 0, CTR_DRBG_MAX_SEED_INPUT );
243
244 /*
Paul Bakker69e095c2011-12-10 21:55:01 +0000245 * Gather enropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000246 */
247 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
248 ctx->entropy_len ) )
249 {
250 return( POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
251 }
252
253 seedlen += ctx->entropy_len;
254
255 /*
256 * Add additional data
257 */
258 if( additional && len )
259 {
260 memcpy( seed + seedlen, additional, len );
261 seedlen += len;
262 }
263
264 /*
265 * Reduce to 384 bits
266 */
267 block_cipher_df( seed, seed, seedlen );
268
269 /*
270 * Update state
271 */
272 ctr_drbg_update_internal( ctx, seed );
273 ctx->reseed_counter = 1;
274
275 return( 0 );
276}
277
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000278int ctr_drbg_random_with_add( void *p_rng,
279 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000280 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000281{
282 int ret = 0;
283 ctr_drbg_context *ctx = (ctr_drbg_context *) p_rng;
284 unsigned char add_input[CTR_DRBG_SEEDLEN];
285 unsigned char *p = output;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000286 unsigned char tmp[CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000287 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000288 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000289
290 if( output_len > CTR_DRBG_MAX_REQUEST )
291 return( POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG );
292
293 if( add_len > CTR_DRBG_MAX_INPUT )
294 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
295
296 memset( add_input, 0, CTR_DRBG_SEEDLEN );
297
298 if( ctx->reseed_counter > ctx->reseed_interval ||
299 ctx->prediction_resistance )
300 {
301 if( ( ret = ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
302 return( ret );
303
304 add_len = 0;
305 }
306
307 if( add_len > 0 )
308 {
309 block_cipher_df( add_input, additional, add_len );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000310 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000311 }
312
313 while( output_len > 0 )
314 {
315 /*
316 * Increase counter
317 */
Paul Bakker369e14b2012-04-18 14:16:09 +0000318 for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
319 if( ++ctx->counter[i - 1] != 0 )
320 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000321
322 /*
323 * Crypt counter block
324 */
325 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, tmp );
326
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000327 use_len = (output_len > CTR_DRBG_BLOCKSIZE ) ? CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000328 /*
329 * Copy random block to destination
330 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000331 memcpy( p, tmp, use_len );
332 p += use_len;
333 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000334 }
335
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000336 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000337
338 ctx->reseed_counter++;
339
340 return( 0 );
341}
342
343int ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
344{
345 return ctr_drbg_random_with_add( p_rng, output, output_len, NULL, 0 );
346}
347
Paul Bakkerfc754a92011-12-05 13:23:51 +0000348#if defined(POLARSSL_FS_IO)
349int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path )
350{
351 int ret;
352 FILE *f;
353 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
354
355 if( ( f = fopen( path, "wb" ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000356 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000357
358 if( ( ret = ctr_drbg_random( ctx, buf, CTR_DRBG_MAX_INPUT ) ) != 0 )
359 return( ret );
360
361 if( fwrite( buf, 1, CTR_DRBG_MAX_INPUT, f ) != CTR_DRBG_MAX_INPUT )
362 {
363 fclose( f );
Paul Bakker69e095c2011-12-10 21:55:01 +0000364 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000365 }
366
367 fclose( f );
368 return( 0 );
369}
370
371int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path )
372{
373 FILE *f;
374 size_t n;
375 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
376
377 if( ( f = fopen( path, "rb" ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000378 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000379
380 fseek( f, 0, SEEK_END );
381 n = (size_t) ftell( f );
382 fseek( f, 0, SEEK_SET );
383
384 if( n > CTR_DRBG_MAX_INPUT )
385 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
386
387 if( fread( buf, 1, n, f ) != n )
388 {
389 fclose( f );
Paul Bakker69e095c2011-12-10 21:55:01 +0000390 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000391 }
392
393 ctr_drbg_update( ctx, buf, n );
394
395 fclose( f );
396
397 return( ctr_drbg_write_seed_file( ctx, path ) );
398}
399#endif /* POLARSSL_FS_IO */
400
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000401#if defined(POLARSSL_SELF_TEST)
402
403#include <stdio.h>
404
405unsigned char entropy_source_pr[96] =
406 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
407 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
408 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
409 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
410 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
411 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
412 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
413 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
414 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
415 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
416 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
417 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
418
419unsigned char entropy_source_nopr[64] =
420 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
421 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
422 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
423 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
424 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
425 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
426 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
427 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
428
429unsigned char nonce_pers_pr[16] =
430 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
431 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
432
433unsigned char nonce_pers_nopr[16] =
434 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
435 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
436
437unsigned char result_pr[16] =
438 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
439 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
440
441unsigned char result_nopr[16] =
442 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
443 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
444
445int test_offset;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000446int ctr_drbg_self_test_entropy( void *data, unsigned char *buf, size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000447{
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000448 unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000449 memcpy( buf, p + test_offset, len );
450 test_offset += 32;
451 return( 0 );
452}
453
454/*
455 * Checkup routine
456 */
457int ctr_drbg_self_test( int verbose )
458{
459 ctr_drbg_context ctx;
460 unsigned char buf[16];
461
462 /*
463 * Based on a NIST CTR_DRBG test vector (PR = True)
464 */
465 if( verbose != 0 )
466 printf( " CTR_DRBG (PR = TRUE) : " );
467
468 test_offset = 0;
Paul Bakkere88186d2012-01-22 20:29:47 +0000469 if( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy, entropy_source_pr, nonce_pers_pr, 16, 32 ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000470 {
471 if( verbose != 0 )
472 printf( "failed\n" );
473
474 return( 1 );
475 }
476 ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON );
477
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000478 if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000479 {
480 if( verbose != 0 )
481 printf( "failed\n" );
482
483 return( 1 );
484 }
485
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000486 if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000487 {
488 if( verbose != 0 )
489 printf( "failed\n" );
490
491 return( 1 );
492 }
493
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000494 if( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000495 {
496 if( verbose != 0 )
497 printf( "failed\n" );
498
499 return( 1 );
500 }
501
502 if( verbose != 0 )
503 printf( "passed\n" );
504
505 /*
506 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
507 */
508 if( verbose != 0 )
509 printf( " CTR_DRBG (PR = FALSE): " );
510
511 test_offset = 0;
Paul Bakkere88186d2012-01-22 20:29:47 +0000512 if( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy, entropy_source_nopr, nonce_pers_nopr, 16, 32 ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000513 {
514 if( verbose != 0 )
515 printf( "failed\n" );
516
517 return( 1 );
518 }
519
520 if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
521 {
522 if( verbose != 0 )
523 printf( "failed\n" );
524
525 return( 1 );
526 }
527
528 if( ctr_drbg_reseed( &ctx, NULL, 0 ) != 0 )
529 {
530 if( verbose != 0 )
531 printf( "failed\n" );
532
533 return( 1 );
534 }
535
536 if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
537 {
538 if( verbose != 0 )
539 printf( "failed\n" );
540
541 return( 1 );
542 }
543
544 if( memcmp( buf, result_nopr, 16 ) != 0 )
545 {
546 if( verbose != 0 )
547 printf( "failed\n" );
548
549 return( 1 );
550 }
551
552 if( verbose != 0 )
553 printf( "passed\n" );
554
555 if( verbose != 0 )
556 printf( "\n" );
557
558 return( 0 );
559}
560#endif
561
562#endif