blob: 1b46f451a6dae2e339131348d3150bb6ba1a3ac5 [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,
Paul Bakker1d073c52014-07-08 20:15:51 +020051 size_t entropy_len );
52
53int ctr_drbg_init_entropy_len(
54 ctr_drbg_context *ctx,
55 int (*f_entropy)(void *, unsigned char *, size_t),
56 void *p_entropy,
57 const unsigned char *custom,
58 size_t len,
Paul Bakker18d32912011-12-10 21:42:49 +000059 size_t entropy_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000060{
61 int ret;
Paul Bakker2bc7cf12011-11-29 10:50:51 +000062 unsigned char key[CTR_DRBG_KEYSIZE];
Paul Bakker0e04d0e2011-11-27 14:46:59 +000063
64 memset( ctx, 0, sizeof(ctr_drbg_context) );
Paul Bakker2bc7cf12011-11-29 10:50:51 +000065 memset( key, 0, CTR_DRBG_KEYSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000066
67 ctx->f_entropy = f_entropy;
68 ctx->p_entropy = p_entropy;
69
Paul Bakker18d32912011-12-10 21:42:49 +000070 ctx->entropy_len = entropy_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +000071 ctx->reseed_interval = CTR_DRBG_RESEED_INTERVAL;
72
73 /*
74 * Initialize with an empty key
75 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +000076 aes_setkey_enc( &ctx->aes_ctx, key, CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000077
78 if( ( ret = ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
79 return( ret );
80
81 return( 0 );
82}
83
Paul Bakker18d32912011-12-10 21:42:49 +000084int ctr_drbg_init( ctr_drbg_context *ctx,
85 int (*f_entropy)(void *, unsigned char *, size_t),
86 void *p_entropy,
87 const unsigned char *custom,
88 size_t len )
89{
90 return( ctr_drbg_init_entropy_len( ctx, f_entropy, p_entropy, custom, len,
91 CTR_DRBG_ENTROPY_LEN ) );
92}
93
Paul Bakker0e04d0e2011-11-27 14:46:59 +000094void ctr_drbg_set_prediction_resistance( ctr_drbg_context *ctx, int resistance )
95{
96 ctx->prediction_resistance = resistance;
97}
98
99void ctr_drbg_set_entropy_len( ctr_drbg_context *ctx, size_t len )
100{
101 ctx->entropy_len = len;
102}
103
104void ctr_drbg_set_reseed_interval( ctr_drbg_context *ctx, int interval )
105{
106 ctx->reseed_interval = interval;
107}
108
Paul Bakker1d073c52014-07-08 20:15:51 +0200109static int block_cipher_df( unsigned char *output,
110 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000111{
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000112 unsigned char buf[CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000113 unsigned char tmp[CTR_DRBG_SEEDLEN];
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000114 unsigned char key[CTR_DRBG_KEYSIZE];
115 unsigned char chain[CTR_DRBG_BLOCKSIZE];
Paul Bakker78370262014-07-07 16:00:26 +0200116 unsigned char *p, *iv;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000117 aes_context aes_ctx;
118
119 int i, j, buf_len, use_len;
120
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000121 memset( buf, 0, CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16 );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000122
123 /*
124 * Construct IV (16 bytes) and S in buffer
125 * IV = Counter (in 32-bits) padded to 16 with zeroes
126 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
127 * data || 0x80
128 * (Total is padded to a multiple of 16-bytes with zeroes)
129 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000130 p = buf + CTR_DRBG_BLOCKSIZE;
131 *p++ = ( data_len >> 24 ) & 0xff;
132 *p++ = ( data_len >> 16 ) & 0xff;
133 *p++ = ( data_len >> 8 ) & 0xff;
134 *p++ = ( data_len ) & 0xff;
135 p += 3;
136 *p++ = CTR_DRBG_SEEDLEN;
137 memcpy( p, data, data_len );
138 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000139
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000140 buf_len = CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000141
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000142 for( i = 0; i < CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000143 key[i] = i;
144
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000145 aes_setkey_enc( &aes_ctx, key, CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000146
147 /*
148 * Reduce data to POLARSSL_CTR_DRBG_SEEDLEN bytes of data
149 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000150 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000151 {
152 p = buf;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000153 memset( chain, 0, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000154 use_len = buf_len;
155
156 while( use_len > 0 )
157 {
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000158 for( i = 0; i < CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000159 chain[i] ^= p[i];
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000160 p += CTR_DRBG_BLOCKSIZE;
161 use_len -= CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000162
163 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, chain, chain );
164 }
165
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000166 memcpy( tmp + j, chain, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000167
168 /*
169 * Update IV
170 */
171 buf[3]++;
172 }
173
174 /*
175 * Do final encryption with reduced data
176 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000177 aes_setkey_enc( &aes_ctx, tmp, CTR_DRBG_KEYBITS );
178 iv = tmp + CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000179 p = output;
180
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000181 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000182 {
183 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, iv, iv );
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000184 memcpy( p, iv, CTR_DRBG_BLOCKSIZE );
185 p += CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000186 }
187
188 return( 0 );
189}
190
Paul Bakker1d073c52014-07-08 20:15:51 +0200191static int ctr_drbg_update_internal( ctr_drbg_context *ctx,
192 const unsigned char data[CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000193{
194 unsigned char tmp[CTR_DRBG_SEEDLEN];
195 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000196 int i, j;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000197
198 memset( tmp, 0, CTR_DRBG_SEEDLEN );
199
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000200 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000201 {
202 /*
203 * Increase counter
204 */
Paul Bakker9a736322012-11-14 12:39:52 +0000205 for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000206 if( ++ctx->counter[i - 1] != 0 )
207 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000208
209 /*
210 * Crypt counter block
211 */
212 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, p );
213
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000214 p += CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000215 }
216
217 for( i = 0; i < CTR_DRBG_SEEDLEN; i++ )
218 tmp[i] ^= data[i];
219
220 /*
221 * Update key and counter
222 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000223 aes_setkey_enc( &ctx->aes_ctx, tmp, CTR_DRBG_KEYBITS );
224 memcpy( ctx->counter, tmp + CTR_DRBG_KEYSIZE, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000225
226 return( 0 );
227}
228
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000229void ctr_drbg_update( ctr_drbg_context *ctx,
230 const unsigned char *additional, size_t add_len )
231{
232 unsigned char add_input[CTR_DRBG_SEEDLEN];
233
234 if( add_len > 0 )
235 {
236 block_cipher_df( add_input, additional, add_len );
237 ctr_drbg_update_internal( ctx, add_input );
238 }
239}
240
241int ctr_drbg_reseed( ctr_drbg_context *ctx,
242 const unsigned char *additional, size_t len )
243{
244 unsigned char seed[CTR_DRBG_MAX_SEED_INPUT];
245 size_t seedlen = 0;
246
247 if( ctx->entropy_len + len > CTR_DRBG_MAX_SEED_INPUT )
248 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
249
250 memset( seed, 0, CTR_DRBG_MAX_SEED_INPUT );
251
252 /*
Paul Bakker69e095c2011-12-10 21:55:01 +0000253 * Gather enropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000254 */
255 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
256 ctx->entropy_len ) )
257 {
258 return( POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
259 }
260
261 seedlen += ctx->entropy_len;
262
263 /*
264 * Add additional data
265 */
266 if( additional && len )
267 {
268 memcpy( seed + seedlen, additional, len );
269 seedlen += len;
270 }
271
272 /*
273 * Reduce to 384 bits
274 */
275 block_cipher_df( seed, seed, seedlen );
276
277 /*
278 * Update state
279 */
280 ctr_drbg_update_internal( ctx, seed );
281 ctx->reseed_counter = 1;
282
283 return( 0 );
284}
285
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000286int ctr_drbg_random_with_add( void *p_rng,
287 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000288 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000289{
290 int ret = 0;
291 ctr_drbg_context *ctx = (ctr_drbg_context *) p_rng;
292 unsigned char add_input[CTR_DRBG_SEEDLEN];
293 unsigned char *p = output;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000294 unsigned char tmp[CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000295 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000296 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000297
298 if( output_len > CTR_DRBG_MAX_REQUEST )
299 return( POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG );
300
301 if( add_len > CTR_DRBG_MAX_INPUT )
302 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
303
304 memset( add_input, 0, CTR_DRBG_SEEDLEN );
305
306 if( ctx->reseed_counter > ctx->reseed_interval ||
307 ctx->prediction_resistance )
308 {
309 if( ( ret = ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
310 return( ret );
311
312 add_len = 0;
313 }
314
315 if( add_len > 0 )
316 {
317 block_cipher_df( add_input, additional, add_len );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000318 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000319 }
320
321 while( output_len > 0 )
322 {
323 /*
324 * Increase counter
325 */
Paul Bakker369e14b2012-04-18 14:16:09 +0000326 for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
327 if( ++ctx->counter[i - 1] != 0 )
328 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000329
330 /*
331 * Crypt counter block
332 */
333 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, tmp );
334
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000335 use_len = (output_len > CTR_DRBG_BLOCKSIZE ) ? CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000336 /*
337 * Copy random block to destination
338 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000339 memcpy( p, tmp, use_len );
340 p += use_len;
341 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000342 }
343
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000344 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000345
346 ctx->reseed_counter++;
347
348 return( 0 );
349}
350
351int ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
352{
353 return ctr_drbg_random_with_add( p_rng, output, output_len, NULL, 0 );
354}
355
Paul Bakkerfc754a92011-12-05 13:23:51 +0000356#if defined(POLARSSL_FS_IO)
357int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path )
358{
359 int ret;
360 FILE *f;
361 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
362
363 if( ( f = fopen( path, "wb" ) ) == NULL )
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 if( ( ret = ctr_drbg_random( ctx, buf, CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakker88a22642013-09-11 12:14:16 +0200367 {
368 fclose( f );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000369 return( ret );
Paul Bakker88a22642013-09-11 12:14:16 +0200370 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000371
372 if( fwrite( buf, 1, CTR_DRBG_MAX_INPUT, f ) != CTR_DRBG_MAX_INPUT )
373 {
374 fclose( f );
Paul Bakker69e095c2011-12-10 21:55:01 +0000375 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000376 }
377
378 fclose( f );
379 return( 0 );
380}
381
382int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path )
383{
384 FILE *f;
385 size_t n;
386 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
387
388 if( ( f = fopen( path, "rb" ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000389 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000390
391 fseek( f, 0, SEEK_END );
392 n = (size_t) ftell( f );
393 fseek( f, 0, SEEK_SET );
394
395 if( n > CTR_DRBG_MAX_INPUT )
Paul Bakker88a22642013-09-11 12:14:16 +0200396 {
397 fclose( f );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000398 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker88a22642013-09-11 12:14:16 +0200399 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000400
401 if( fread( buf, 1, n, f ) != n )
402 {
403 fclose( f );
Paul Bakker69e095c2011-12-10 21:55:01 +0000404 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000405 }
406
407 ctr_drbg_update( ctx, buf, n );
408
409 fclose( f );
410
411 return( ctr_drbg_write_seed_file( ctx, path ) );
412}
413#endif /* POLARSSL_FS_IO */
414
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000415#if defined(POLARSSL_SELF_TEST)
416
417#include <stdio.h>
418
419unsigned char entropy_source_pr[96] =
420 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
421 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
422 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
423 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
424 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
425 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
426 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
427 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
428 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
429 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
430 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
431 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
432
433unsigned char entropy_source_nopr[64] =
434 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
435 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
436 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
437 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
438 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
439 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
440 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
441 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
442
443unsigned char nonce_pers_pr[16] =
444 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
445 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
446
447unsigned char nonce_pers_nopr[16] =
448 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
449 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
450
451unsigned char result_pr[16] =
452 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
453 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
454
455unsigned char result_nopr[16] =
456 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
457 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
458
Paul Bakker22a0ce02014-07-08 11:16:44 +0200459static size_t test_offset;
Paul Bakker1d073c52014-07-08 20:15:51 +0200460static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
461 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000462{
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000463 unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000464 memcpy( buf, p + test_offset, len );
465 test_offset += 32;
466 return( 0 );
467}
468
469/*
470 * Checkup routine
471 */
472int ctr_drbg_self_test( int verbose )
473{
474 ctr_drbg_context ctx;
475 unsigned char buf[16];
476
477 /*
478 * Based on a NIST CTR_DRBG test vector (PR = True)
479 */
480 if( verbose != 0 )
481 printf( " CTR_DRBG (PR = TRUE) : " );
482
483 test_offset = 0;
Paul Bakkere88186d2012-01-22 20:29:47 +0000484 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 +0000485 {
486 if( verbose != 0 )
487 printf( "failed\n" );
488
489 return( 1 );
490 }
491 ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON );
492
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000493 if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000494 {
495 if( verbose != 0 )
496 printf( "failed\n" );
497
498 return( 1 );
499 }
500
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000501 if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000502 {
503 if( verbose != 0 )
504 printf( "failed\n" );
505
506 return( 1 );
507 }
508
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000509 if( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000510 {
511 if( verbose != 0 )
512 printf( "failed\n" );
513
514 return( 1 );
515 }
516
517 if( verbose != 0 )
518 printf( "passed\n" );
519
520 /*
521 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
522 */
523 if( verbose != 0 )
524 printf( " CTR_DRBG (PR = FALSE): " );
525
526 test_offset = 0;
Paul Bakkere88186d2012-01-22 20:29:47 +0000527 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 +0000528 {
529 if( verbose != 0 )
530 printf( "failed\n" );
531
532 return( 1 );
533 }
534
535 if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
536 {
537 if( verbose != 0 )
538 printf( "failed\n" );
539
540 return( 1 );
541 }
542
543 if( ctr_drbg_reseed( &ctx, NULL, 0 ) != 0 )
544 {
545 if( verbose != 0 )
546 printf( "failed\n" );
547
548 return( 1 );
549 }
550
551 if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
552 {
553 if( verbose != 0 )
554 printf( "failed\n" );
555
556 return( 1 );
557 }
558
559 if( memcmp( buf, result_nopr, 16 ) != 0 )
560 {
561 if( verbose != 0 )
562 printf( "failed\n" );
563
564 return( 1 );
565 }
566
567 if( verbose != 0 )
568 printf( "passed\n" );
569
570 if( verbose != 0 )
571 printf( "\n" );
572
573 return( 0 );
574}
575#endif
576
577#endif