blob: 980d95486a6d6772946674004c20b1d257e01ccd [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
Manuel Pégourié-Gonnard258bab02014-11-25 17:41:50 +0100121 if( data_len > CTR_DRBG_MAX_SEED_INPUT )
122 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
123
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000124 memset( buf, 0, CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16 );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000125
126 /*
127 * Construct IV (16 bytes) and S in buffer
128 * IV = Counter (in 32-bits) padded to 16 with zeroes
129 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
130 * data || 0x80
131 * (Total is padded to a multiple of 16-bytes with zeroes)
132 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000133 p = buf + CTR_DRBG_BLOCKSIZE;
134 *p++ = ( data_len >> 24 ) & 0xff;
135 *p++ = ( data_len >> 16 ) & 0xff;
136 *p++ = ( data_len >> 8 ) & 0xff;
137 *p++ = ( data_len ) & 0xff;
138 p += 3;
139 *p++ = CTR_DRBG_SEEDLEN;
140 memcpy( p, data, data_len );
141 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000142
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000143 buf_len = CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000144
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000145 for( i = 0; i < CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000146 key[i] = i;
147
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000148 aes_setkey_enc( &aes_ctx, key, CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000149
150 /*
151 * Reduce data to POLARSSL_CTR_DRBG_SEEDLEN bytes of data
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 p = buf;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000156 memset( chain, 0, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000157 use_len = buf_len;
158
159 while( use_len > 0 )
160 {
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000161 for( i = 0; i < CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000162 chain[i] ^= p[i];
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000163 p += CTR_DRBG_BLOCKSIZE;
164 use_len -= CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000165
166 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, chain, chain );
167 }
168
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000169 memcpy( tmp + j, chain, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000170
171 /*
172 * Update IV
173 */
174 buf[3]++;
175 }
176
177 /*
178 * Do final encryption with reduced data
179 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000180 aes_setkey_enc( &aes_ctx, tmp, CTR_DRBG_KEYBITS );
181 iv = tmp + CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000182 p = output;
183
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000184 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000185 {
186 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, iv, iv );
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000187 memcpy( p, iv, CTR_DRBG_BLOCKSIZE );
188 p += CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000189 }
190
191 return( 0 );
192}
193
Paul Bakker1d073c52014-07-08 20:15:51 +0200194static int ctr_drbg_update_internal( ctr_drbg_context *ctx,
195 const unsigned char data[CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000196{
197 unsigned char tmp[CTR_DRBG_SEEDLEN];
198 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000199 int i, j;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000200
201 memset( tmp, 0, CTR_DRBG_SEEDLEN );
202
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000203 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000204 {
205 /*
206 * Increase counter
207 */
Paul Bakker9a736322012-11-14 12:39:52 +0000208 for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000209 if( ++ctx->counter[i - 1] != 0 )
210 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000211
212 /*
213 * Crypt counter block
214 */
215 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, p );
216
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000217 p += CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000218 }
219
220 for( i = 0; i < CTR_DRBG_SEEDLEN; i++ )
221 tmp[i] ^= data[i];
222
223 /*
224 * Update key and counter
225 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000226 aes_setkey_enc( &ctx->aes_ctx, tmp, CTR_DRBG_KEYBITS );
227 memcpy( ctx->counter, tmp + CTR_DRBG_KEYSIZE, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000228
229 return( 0 );
230}
231
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000232void ctr_drbg_update( ctr_drbg_context *ctx,
233 const unsigned char *additional, size_t add_len )
234{
235 unsigned char add_input[CTR_DRBG_SEEDLEN];
236
237 if( add_len > 0 )
238 {
Manuel Pégourié-Gonnard258bab02014-11-25 17:41:50 +0100239 /* MAX_INPUT would be more logical here, but we have to match
240 * block_cipher_df()'s limits since we can't propagate errors */
241 if( add_len > CTR_DRBG_MAX_SEED_INPUT )
242 add_len = CTR_DRBG_MAX_SEED_INPUT;
243
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000244 block_cipher_df( add_input, additional, add_len );
245 ctr_drbg_update_internal( ctx, add_input );
246 }
247}
248
249int ctr_drbg_reseed( ctr_drbg_context *ctx,
250 const unsigned char *additional, size_t len )
251{
252 unsigned char seed[CTR_DRBG_MAX_SEED_INPUT];
253 size_t seedlen = 0;
254
255 if( ctx->entropy_len + len > CTR_DRBG_MAX_SEED_INPUT )
256 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
257
258 memset( seed, 0, CTR_DRBG_MAX_SEED_INPUT );
259
260 /*
Paul Bakker69e095c2011-12-10 21:55:01 +0000261 * Gather enropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000262 */
263 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
264 ctx->entropy_len ) )
265 {
266 return( POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
267 }
268
269 seedlen += ctx->entropy_len;
270
271 /*
272 * Add additional data
273 */
274 if( additional && len )
275 {
276 memcpy( seed + seedlen, additional, len );
277 seedlen += len;
278 }
279
280 /*
281 * Reduce to 384 bits
282 */
283 block_cipher_df( seed, seed, seedlen );
284
285 /*
286 * Update state
287 */
288 ctr_drbg_update_internal( ctx, seed );
289 ctx->reseed_counter = 1;
290
291 return( 0 );
292}
293
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000294int ctr_drbg_random_with_add( void *p_rng,
295 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000296 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000297{
298 int ret = 0;
299 ctr_drbg_context *ctx = (ctr_drbg_context *) p_rng;
300 unsigned char add_input[CTR_DRBG_SEEDLEN];
301 unsigned char *p = output;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000302 unsigned char tmp[CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000303 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000304 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000305
306 if( output_len > CTR_DRBG_MAX_REQUEST )
307 return( POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG );
308
309 if( add_len > CTR_DRBG_MAX_INPUT )
310 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
311
312 memset( add_input, 0, CTR_DRBG_SEEDLEN );
313
314 if( ctx->reseed_counter > ctx->reseed_interval ||
315 ctx->prediction_resistance )
316 {
317 if( ( ret = ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
318 return( ret );
319
320 add_len = 0;
321 }
322
323 if( add_len > 0 )
324 {
325 block_cipher_df( add_input, additional, add_len );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000326 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000327 }
328
329 while( output_len > 0 )
330 {
331 /*
332 * Increase counter
333 */
Paul Bakker369e14b2012-04-18 14:16:09 +0000334 for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
335 if( ++ctx->counter[i - 1] != 0 )
336 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000337
338 /*
339 * Crypt counter block
340 */
341 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, tmp );
342
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000343 use_len = (output_len > CTR_DRBG_BLOCKSIZE ) ? CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000344 /*
345 * Copy random block to destination
346 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000347 memcpy( p, tmp, use_len );
348 p += use_len;
349 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000350 }
351
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000352 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000353
354 ctx->reseed_counter++;
355
356 return( 0 );
357}
358
359int ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
360{
361 return ctr_drbg_random_with_add( p_rng, output, output_len, NULL, 0 );
362}
363
Paul Bakkerfc754a92011-12-05 13:23:51 +0000364#if defined(POLARSSL_FS_IO)
365int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path )
366{
367 int ret;
368 FILE *f;
369 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
370
371 if( ( f = fopen( path, "wb" ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000372 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000373
374 if( ( ret = ctr_drbg_random( ctx, buf, CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakker88a22642013-09-11 12:14:16 +0200375 {
376 fclose( f );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000377 return( ret );
Paul Bakker88a22642013-09-11 12:14:16 +0200378 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000379
380 if( fwrite( buf, 1, CTR_DRBG_MAX_INPUT, f ) != CTR_DRBG_MAX_INPUT )
381 {
382 fclose( f );
Paul Bakker69e095c2011-12-10 21:55:01 +0000383 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000384 }
385
386 fclose( f );
387 return( 0 );
388}
389
390int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path )
391{
392 FILE *f;
393 size_t n;
394 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
395
396 if( ( f = fopen( path, "rb" ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000397 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000398
399 fseek( f, 0, SEEK_END );
400 n = (size_t) ftell( f );
401 fseek( f, 0, SEEK_SET );
402
403 if( n > CTR_DRBG_MAX_INPUT )
Paul Bakker88a22642013-09-11 12:14:16 +0200404 {
405 fclose( f );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000406 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker88a22642013-09-11 12:14:16 +0200407 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000408
409 if( fread( buf, 1, n, f ) != n )
410 {
411 fclose( f );
Paul Bakker69e095c2011-12-10 21:55:01 +0000412 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000413 }
414
415 ctr_drbg_update( ctx, buf, n );
416
417 fclose( f );
418
419 return( ctr_drbg_write_seed_file( ctx, path ) );
420}
421#endif /* POLARSSL_FS_IO */
422
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000423#if defined(POLARSSL_SELF_TEST)
424
425#include <stdio.h>
426
427unsigned char entropy_source_pr[96] =
428 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
429 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
430 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
431 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
432 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
433 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
434 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
435 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
436 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
437 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
438 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
439 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
440
441unsigned char entropy_source_nopr[64] =
442 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
443 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
444 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
445 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
446 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
447 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
448 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
449 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
450
451unsigned char nonce_pers_pr[16] =
452 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
453 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
454
455unsigned char nonce_pers_nopr[16] =
456 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
457 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
458
459unsigned char result_pr[16] =
460 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
461 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
462
463unsigned char result_nopr[16] =
464 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
465 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
466
Paul Bakker22a0ce02014-07-08 11:16:44 +0200467static size_t test_offset;
Paul Bakker1d073c52014-07-08 20:15:51 +0200468static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
469 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000470{
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000471 unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000472 memcpy( buf, p + test_offset, len );
473 test_offset += 32;
474 return( 0 );
475}
476
477/*
478 * Checkup routine
479 */
480int ctr_drbg_self_test( int verbose )
481{
482 ctr_drbg_context ctx;
483 unsigned char buf[16];
484
485 /*
486 * Based on a NIST CTR_DRBG test vector (PR = True)
487 */
488 if( verbose != 0 )
489 printf( " CTR_DRBG (PR = TRUE) : " );
490
491 test_offset = 0;
Paul Bakkere88186d2012-01-22 20:29:47 +0000492 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 +0000493 {
494 if( verbose != 0 )
495 printf( "failed\n" );
496
497 return( 1 );
498 }
499 ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON );
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( ctr_drbg_random( &ctx, buf, 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
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000517 if( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000518 {
519 if( verbose != 0 )
520 printf( "failed\n" );
521
522 return( 1 );
523 }
524
525 if( verbose != 0 )
526 printf( "passed\n" );
527
528 /*
529 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
530 */
531 if( verbose != 0 )
532 printf( " CTR_DRBG (PR = FALSE): " );
533
534 test_offset = 0;
Paul Bakkere88186d2012-01-22 20:29:47 +0000535 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 +0000536 {
537 if( verbose != 0 )
538 printf( "failed\n" );
539
540 return( 1 );
541 }
542
543 if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
544 {
545 if( verbose != 0 )
546 printf( "failed\n" );
547
548 return( 1 );
549 }
550
551 if( ctr_drbg_reseed( &ctx, NULL, 0 ) != 0 )
552 {
553 if( verbose != 0 )
554 printf( "failed\n" );
555
556 return( 1 );
557 }
558
559 if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
560 {
561 if( verbose != 0 )
562 printf( "failed\n" );
563
564 return( 1 );
565 }
566
567 if( memcmp( buf, result_nopr, 16 ) != 0 )
568 {
569 if( verbose != 0 )
570 printf( "failed\n" );
571
572 return( 1 );
573 }
574
575 if( verbose != 0 )
576 printf( "passed\n" );
577
578 if( verbose != 0 )
579 printf( "\n" );
580
581 return( 0 );
582}
583#endif
584
585#endif