blob: 4aaf774d404367c86bcf232431cbbc3f0dedfe8a [file] [log] [blame]
Paul Bakker0e04d0e2011-11-27 14:46:59 +00001/*
2 * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
3 *
Manuel Pégourié-Gonnard0edee5e2015-01-26 15:29:40 +00004 * Copyright (C) 2006-2011, ARM Limited, All Rights Reserved
Paul Bakker0e04d0e2011-11-27 14:46:59 +00005 *
Manuel Pégourié-Gonnarde12abf92015-01-28 17:13:45 +00006 * This file is part of mbed TLS (https://polarssl.org)
Paul Bakker0e04d0e2011-11-27 14:46:59 +00007 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22/*
23 * The NIST SP 800-90 DRBGs are described in the following publucation.
24 *
25 * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
26 */
27
28#include "polarssl/config.h"
29
30#if defined(POLARSSL_CTR_DRBG_C)
31
32#include "polarssl/ctr_drbg.h"
33
Paul Bakkerfc754a92011-12-05 13:23:51 +000034#if defined(POLARSSL_FS_IO)
35#include <stdio.h>
36#endif
37
Paul Bakker18d32912011-12-10 21:42:49 +000038/*
39 * Non-public function wrapped by ctr_crbg_init(). Necessary to allow NIST
40 * tests to succeed (which require known length fixed entropy)
41 */
42int ctr_drbg_init_entropy_len(
43 ctr_drbg_context *ctx,
Paul Bakker0e04d0e2011-11-27 14:46:59 +000044 int (*f_entropy)(void *, unsigned char *, size_t),
45 void *p_entropy,
Paul Bakker1bc9efc2011-12-03 11:29:32 +000046 const unsigned char *custom,
Paul Bakker18d32912011-12-10 21:42:49 +000047 size_t len,
Paul Bakker1d073c52014-07-08 20:15:51 +020048 size_t entropy_len );
49
50int ctr_drbg_init_entropy_len(
51 ctr_drbg_context *ctx,
52 int (*f_entropy)(void *, unsigned char *, size_t),
53 void *p_entropy,
54 const unsigned char *custom,
55 size_t len,
Paul Bakker18d32912011-12-10 21:42:49 +000056 size_t entropy_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000057{
58 int ret;
Paul Bakker2bc7cf12011-11-29 10:50:51 +000059 unsigned char key[CTR_DRBG_KEYSIZE];
Paul Bakker0e04d0e2011-11-27 14:46:59 +000060
61 memset( ctx, 0, sizeof(ctr_drbg_context) );
Paul Bakker2bc7cf12011-11-29 10:50:51 +000062 memset( key, 0, CTR_DRBG_KEYSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000063
64 ctx->f_entropy = f_entropy;
65 ctx->p_entropy = p_entropy;
66
Paul Bakker18d32912011-12-10 21:42:49 +000067 ctx->entropy_len = entropy_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +000068 ctx->reseed_interval = CTR_DRBG_RESEED_INTERVAL;
69
70 /*
71 * Initialize with an empty key
72 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +000073 aes_setkey_enc( &ctx->aes_ctx, key, CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000074
75 if( ( ret = ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
76 return( ret );
77
78 return( 0 );
79}
80
Paul Bakker18d32912011-12-10 21:42:49 +000081int ctr_drbg_init( ctr_drbg_context *ctx,
82 int (*f_entropy)(void *, unsigned char *, size_t),
83 void *p_entropy,
84 const unsigned char *custom,
85 size_t len )
86{
87 return( ctr_drbg_init_entropy_len( ctx, f_entropy, p_entropy, custom, len,
88 CTR_DRBG_ENTROPY_LEN ) );
89}
90
Paul Bakker0e04d0e2011-11-27 14:46:59 +000091void ctr_drbg_set_prediction_resistance( ctr_drbg_context *ctx, int resistance )
92{
93 ctx->prediction_resistance = resistance;
94}
95
96void ctr_drbg_set_entropy_len( ctr_drbg_context *ctx, size_t len )
97{
98 ctx->entropy_len = len;
99}
100
101void ctr_drbg_set_reseed_interval( ctr_drbg_context *ctx, int interval )
102{
103 ctx->reseed_interval = interval;
104}
105
Paul Bakker1d073c52014-07-08 20:15:51 +0200106static int block_cipher_df( unsigned char *output,
107 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000108{
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000109 unsigned char buf[CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000110 unsigned char tmp[CTR_DRBG_SEEDLEN];
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000111 unsigned char key[CTR_DRBG_KEYSIZE];
112 unsigned char chain[CTR_DRBG_BLOCKSIZE];
Paul Bakker78370262014-07-07 16:00:26 +0200113 unsigned char *p, *iv;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000114 aes_context aes_ctx;
115
116 int i, j, buf_len, use_len;
117
Manuel Pégourié-Gonnard258bab02014-11-25 17:41:50 +0100118 if( data_len > CTR_DRBG_MAX_SEED_INPUT )
119 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
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 {
Manuel Pégourié-Gonnard258bab02014-11-25 17:41:50 +0100236 /* MAX_INPUT would be more logical here, but we have to match
237 * block_cipher_df()'s limits since we can't propagate errors */
238 if( add_len > CTR_DRBG_MAX_SEED_INPUT )
239 add_len = CTR_DRBG_MAX_SEED_INPUT;
240
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000241 block_cipher_df( add_input, additional, add_len );
242 ctr_drbg_update_internal( ctx, add_input );
243 }
244}
245
246int ctr_drbg_reseed( ctr_drbg_context *ctx,
247 const unsigned char *additional, size_t len )
248{
249 unsigned char seed[CTR_DRBG_MAX_SEED_INPUT];
250 size_t seedlen = 0;
251
252 if( ctx->entropy_len + len > CTR_DRBG_MAX_SEED_INPUT )
253 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
254
255 memset( seed, 0, CTR_DRBG_MAX_SEED_INPUT );
256
257 /*
Paul Bakker69e095c2011-12-10 21:55:01 +0000258 * Gather enropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000259 */
260 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
261 ctx->entropy_len ) )
262 {
263 return( POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
264 }
265
266 seedlen += ctx->entropy_len;
267
268 /*
269 * Add additional data
270 */
271 if( additional && len )
272 {
273 memcpy( seed + seedlen, additional, len );
274 seedlen += len;
275 }
276
277 /*
278 * Reduce to 384 bits
279 */
280 block_cipher_df( seed, seed, seedlen );
281
282 /*
283 * Update state
284 */
285 ctr_drbg_update_internal( ctx, seed );
286 ctx->reseed_counter = 1;
287
288 return( 0 );
289}
290
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000291int ctr_drbg_random_with_add( void *p_rng,
292 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000293 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000294{
295 int ret = 0;
296 ctr_drbg_context *ctx = (ctr_drbg_context *) p_rng;
297 unsigned char add_input[CTR_DRBG_SEEDLEN];
298 unsigned char *p = output;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000299 unsigned char tmp[CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000300 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000301 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000302
303 if( output_len > CTR_DRBG_MAX_REQUEST )
304 return( POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG );
305
306 if( add_len > CTR_DRBG_MAX_INPUT )
307 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
308
309 memset( add_input, 0, CTR_DRBG_SEEDLEN );
310
311 if( ctx->reseed_counter > ctx->reseed_interval ||
312 ctx->prediction_resistance )
313 {
314 if( ( ret = ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
315 return( ret );
316
317 add_len = 0;
318 }
319
320 if( add_len > 0 )
321 {
322 block_cipher_df( add_input, additional, add_len );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000323 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000324 }
325
326 while( output_len > 0 )
327 {
328 /*
329 * Increase counter
330 */
Paul Bakker369e14b2012-04-18 14:16:09 +0000331 for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
332 if( ++ctx->counter[i - 1] != 0 )
333 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000334
335 /*
336 * Crypt counter block
337 */
338 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, tmp );
339
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000340 use_len = (output_len > CTR_DRBG_BLOCKSIZE ) ? CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000341 /*
342 * Copy random block to destination
343 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000344 memcpy( p, tmp, use_len );
345 p += use_len;
346 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000347 }
348
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000349 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000350
351 ctx->reseed_counter++;
352
353 return( 0 );
354}
355
356int ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
357{
358 return ctr_drbg_random_with_add( p_rng, output, output_len, NULL, 0 );
359}
360
Paul Bakkerfc754a92011-12-05 13:23:51 +0000361#if defined(POLARSSL_FS_IO)
362int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path )
363{
364 int ret;
365 FILE *f;
366 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
367
368 if( ( f = fopen( path, "wb" ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000369 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000370
371 if( ( ret = ctr_drbg_random( ctx, buf, CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakker88a22642013-09-11 12:14:16 +0200372 {
373 fclose( f );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000374 return( ret );
Paul Bakker88a22642013-09-11 12:14:16 +0200375 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000376
377 if( fwrite( buf, 1, CTR_DRBG_MAX_INPUT, f ) != CTR_DRBG_MAX_INPUT )
378 {
379 fclose( f );
Paul Bakker69e095c2011-12-10 21:55:01 +0000380 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000381 }
382
383 fclose( f );
384 return( 0 );
385}
386
387int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path )
388{
389 FILE *f;
390 size_t n;
391 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
392
393 if( ( f = fopen( path, "rb" ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000394 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000395
396 fseek( f, 0, SEEK_END );
397 n = (size_t) ftell( f );
398 fseek( f, 0, SEEK_SET );
399
400 if( n > CTR_DRBG_MAX_INPUT )
Paul Bakker88a22642013-09-11 12:14:16 +0200401 {
402 fclose( f );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000403 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker88a22642013-09-11 12:14:16 +0200404 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000405
406 if( fread( buf, 1, n, f ) != n )
407 {
408 fclose( f );
Paul Bakker69e095c2011-12-10 21:55:01 +0000409 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000410 }
411
412 ctr_drbg_update( ctx, buf, n );
413
414 fclose( f );
415
416 return( ctr_drbg_write_seed_file( ctx, path ) );
417}
418#endif /* POLARSSL_FS_IO */
419
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000420#if defined(POLARSSL_SELF_TEST)
421
422#include <stdio.h>
423
424unsigned char entropy_source_pr[96] =
425 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
426 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
427 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
428 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
429 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
430 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
431 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
432 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
433 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
434 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
435 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
436 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
437
438unsigned char entropy_source_nopr[64] =
439 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
440 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
441 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
442 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
443 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
444 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
445 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
446 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
447
448unsigned char nonce_pers_pr[16] =
449 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
450 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
451
452unsigned char nonce_pers_nopr[16] =
453 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
454 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
455
456unsigned char result_pr[16] =
457 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
458 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
459
460unsigned char result_nopr[16] =
461 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
462 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
463
Paul Bakker22a0ce02014-07-08 11:16:44 +0200464static size_t test_offset;
Paul Bakker1d073c52014-07-08 20:15:51 +0200465static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
466 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000467{
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000468 unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000469 memcpy( buf, p + test_offset, len );
470 test_offset += 32;
471 return( 0 );
472}
473
474/*
475 * Checkup routine
476 */
477int ctr_drbg_self_test( int verbose )
478{
479 ctr_drbg_context ctx;
480 unsigned char buf[16];
481
482 /*
483 * Based on a NIST CTR_DRBG test vector (PR = True)
484 */
485 if( verbose != 0 )
486 printf( " CTR_DRBG (PR = TRUE) : " );
487
488 test_offset = 0;
Paul Bakkere88186d2012-01-22 20:29:47 +0000489 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 +0000490 {
491 if( verbose != 0 )
492 printf( "failed\n" );
493
494 return( 1 );
495 }
496 ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON );
497
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000498 if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000499 {
500 if( verbose != 0 )
501 printf( "failed\n" );
502
503 return( 1 );
504 }
505
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000506 if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000507 {
508 if( verbose != 0 )
509 printf( "failed\n" );
510
511 return( 1 );
512 }
513
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000514 if( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000515 {
516 if( verbose != 0 )
517 printf( "failed\n" );
518
519 return( 1 );
520 }
521
522 if( verbose != 0 )
523 printf( "passed\n" );
524
525 /*
526 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
527 */
528 if( verbose != 0 )
529 printf( " CTR_DRBG (PR = FALSE): " );
530
531 test_offset = 0;
Paul Bakkere88186d2012-01-22 20:29:47 +0000532 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 +0000533 {
534 if( verbose != 0 )
535 printf( "failed\n" );
536
537 return( 1 );
538 }
539
540 if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
541 {
542 if( verbose != 0 )
543 printf( "failed\n" );
544
545 return( 1 );
546 }
547
548 if( ctr_drbg_reseed( &ctx, NULL, 0 ) != 0 )
549 {
550 if( verbose != 0 )
551 printf( "failed\n" );
552
553 return( 1 );
554 }
555
556 if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
557 {
558 if( verbose != 0 )
559 printf( "failed\n" );
560
561 return( 1 );
562 }
563
564 if( memcmp( buf, result_nopr, 16 ) != 0 )
565 {
566 if( verbose != 0 )
567 printf( "failed\n" );
568
569 return( 1 );
570 }
571
572 if( verbose != 0 )
573 printf( "passed\n" );
574
575 if( verbose != 0 )
576 printf( "\n" );
577
578 return( 0 );
579}
580#endif
581
582#endif