blob: 89b4c4c6501198c0187369033a5bce597175cc73 [file] [log] [blame]
Paul Bakker0e04d0e2011-11-27 14:46:59 +00001/*
2 * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
3 *
Paul Bakker7dc4c442014-02-01 22:50:26 +01004 * Copyright (C) 2006-2014, Brainspark B.V.
Paul Bakker0e04d0e2011-11-27 14:46:59 +00005 *
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
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020031#if !defined(POLARSSL_CONFIG_FILE)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000032#include "polarssl/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020033#else
34#include POLARSSL_CONFIG_FILE
35#endif
Paul Bakker0e04d0e2011-11-27 14:46:59 +000036
37#if defined(POLARSSL_CTR_DRBG_C)
38
39#include "polarssl/ctr_drbg.h"
40
Paul Bakkerfc754a92011-12-05 13:23:51 +000041#if defined(POLARSSL_FS_IO)
42#include <stdio.h>
43#endif
44
Paul Bakker7dc4c442014-02-01 22:50:26 +010045#if defined(POLARSSL_PLATFORM_C)
46#include "polarssl/platform.h"
47#else
48#define polarssl_printf printf
49#endif
50
Paul Bakker18d32912011-12-10 21:42:49 +000051/*
52 * Non-public function wrapped by ctr_crbg_init(). Necessary to allow NIST
53 * tests to succeed (which require known length fixed entropy)
54 */
Paul Bakker534f82c2013-06-25 16:47:55 +020055int ctr_drbg_init_entropy_len(
Paul Bakker18d32912011-12-10 21:42:49 +000056 ctr_drbg_context *ctx,
Paul Bakker0e04d0e2011-11-27 14:46:59 +000057 int (*f_entropy)(void *, unsigned char *, size_t),
58 void *p_entropy,
Paul Bakker1bc9efc2011-12-03 11:29:32 +000059 const unsigned char *custom,
Paul Bakker18d32912011-12-10 21:42:49 +000060 size_t len,
61 size_t entropy_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000062{
63 int ret;
Paul Bakker2bc7cf12011-11-29 10:50:51 +000064 unsigned char key[CTR_DRBG_KEYSIZE];
Paul Bakker0e04d0e2011-11-27 14:46:59 +000065
66 memset( ctx, 0, sizeof(ctr_drbg_context) );
Paul Bakker2bc7cf12011-11-29 10:50:51 +000067 memset( key, 0, CTR_DRBG_KEYSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000068
69 ctx->f_entropy = f_entropy;
70 ctx->p_entropy = p_entropy;
71
Paul Bakker18d32912011-12-10 21:42:49 +000072 ctx->entropy_len = entropy_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +000073 ctx->reseed_interval = CTR_DRBG_RESEED_INTERVAL;
74
75 /*
76 * Initialize with an empty key
77 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +000078 aes_setkey_enc( &ctx->aes_ctx, key, CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000079
80 if( ( ret = ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
81 return( ret );
82
83 return( 0 );
84}
85
Paul Bakker18d32912011-12-10 21:42:49 +000086int ctr_drbg_init( ctr_drbg_context *ctx,
87 int (*f_entropy)(void *, unsigned char *, size_t),
88 void *p_entropy,
89 const unsigned char *custom,
90 size_t len )
91{
92 return( ctr_drbg_init_entropy_len( ctx, f_entropy, p_entropy, custom, len,
93 CTR_DRBG_ENTROPY_LEN ) );
94}
95
Paul Bakker0e04d0e2011-11-27 14:46:59 +000096void ctr_drbg_set_prediction_resistance( ctr_drbg_context *ctx, int resistance )
97{
98 ctx->prediction_resistance = resistance;
99}
100
101void ctr_drbg_set_entropy_len( ctr_drbg_context *ctx, size_t len )
102{
103 ctx->entropy_len = len;
104}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200105
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000106void ctr_drbg_set_reseed_interval( ctr_drbg_context *ctx, int interval )
107{
108 ctx->reseed_interval = interval;
109}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200110
111static int block_cipher_df( unsigned char *output,
112 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000113{
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000114 unsigned char buf[CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000115 unsigned char tmp[CTR_DRBG_SEEDLEN];
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000116 unsigned char key[CTR_DRBG_KEYSIZE];
117 unsigned char chain[CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100118 unsigned char *p, *iv;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000119 aes_context aes_ctx;
120
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200121 int i, j;
122 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000123
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;
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200164 use_len -= ( use_len >= CTR_DRBG_BLOCKSIZE ) ?
165 CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000166
167 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, chain, chain );
168 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200169
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000170 memcpy( tmp + j, chain, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000171
172 /*
173 * Update IV
174 */
175 buf[3]++;
176 }
177
178 /*
179 * Do final encryption with reduced data
180 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000181 aes_setkey_enc( &aes_ctx, tmp, CTR_DRBG_KEYBITS );
182 iv = tmp + CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000183 p = output;
184
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000185 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000186 {
187 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, iv, iv );
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000188 memcpy( p, iv, CTR_DRBG_BLOCKSIZE );
189 p += CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000190 }
191
192 return( 0 );
193}
194
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200195static int ctr_drbg_update_internal( ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000196 const unsigned char data[CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000197{
198 unsigned char tmp[CTR_DRBG_SEEDLEN];
199 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000200 int i, j;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000201
202 memset( tmp, 0, CTR_DRBG_SEEDLEN );
203
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000204 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000205 {
206 /*
207 * Increase counter
208 */
Paul Bakker9a736322012-11-14 12:39:52 +0000209 for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000210 if( ++ctx->counter[i - 1] != 0 )
211 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000212
213 /*
214 * Crypt counter block
215 */
216 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, p );
217
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000218 p += CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000219 }
220
221 for( i = 0; i < CTR_DRBG_SEEDLEN; i++ )
222 tmp[i] ^= data[i];
223
224 /*
225 * Update key and counter
226 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000227 aes_setkey_enc( &ctx->aes_ctx, tmp, CTR_DRBG_KEYBITS );
228 memcpy( ctx->counter, tmp + CTR_DRBG_KEYSIZE, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000229
230 return( 0 );
231}
232
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000233void ctr_drbg_update( ctr_drbg_context *ctx,
234 const unsigned char *additional, size_t add_len )
235{
236 unsigned char add_input[CTR_DRBG_SEEDLEN];
237
238 if( add_len > 0 )
239 {
240 block_cipher_df( add_input, additional, add_len );
241 ctr_drbg_update_internal( ctx, add_input );
242 }
243}
244
245int ctr_drbg_reseed( ctr_drbg_context *ctx,
246 const unsigned char *additional, size_t len )
247{
248 unsigned char seed[CTR_DRBG_MAX_SEED_INPUT];
249 size_t seedlen = 0;
250
251 if( ctx->entropy_len + len > CTR_DRBG_MAX_SEED_INPUT )
252 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
253
254 memset( seed, 0, CTR_DRBG_MAX_SEED_INPUT );
255
256 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200257 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000258 */
259 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
260 ctx->entropy_len ) )
261 {
262 return( POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
263 }
264
265 seedlen += ctx->entropy_len;
266
267 /*
268 * Add additional data
269 */
270 if( additional && len )
271 {
272 memcpy( seed + seedlen, additional, len );
273 seedlen += len;
274 }
275
276 /*
277 * Reduce to 384 bits
278 */
279 block_cipher_df( seed, seed, seedlen );
280
281 /*
282 * Update state
283 */
284 ctr_drbg_update_internal( ctx, seed );
285 ctx->reseed_counter = 1;
286
287 return( 0 );
288}
289
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000290int ctr_drbg_random_with_add( void *p_rng,
291 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000292 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000293{
294 int ret = 0;
295 ctr_drbg_context *ctx = (ctr_drbg_context *) p_rng;
296 unsigned char add_input[CTR_DRBG_SEEDLEN];
297 unsigned char *p = output;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000298 unsigned char tmp[CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000299 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000300 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000301
302 if( output_len > CTR_DRBG_MAX_REQUEST )
303 return( POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG );
304
305 if( add_len > CTR_DRBG_MAX_INPUT )
306 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
307
308 memset( add_input, 0, CTR_DRBG_SEEDLEN );
309
310 if( ctx->reseed_counter > ctx->reseed_interval ||
311 ctx->prediction_resistance )
312 {
313 if( ( ret = ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
314 return( ret );
315
316 add_len = 0;
317 }
318
319 if( add_len > 0 )
320 {
321 block_cipher_df( add_input, additional, add_len );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000322 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000323 }
324
325 while( output_len > 0 )
326 {
327 /*
328 * Increase counter
329 */
Paul Bakker369e14b2012-04-18 14:16:09 +0000330 for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
331 if( ++ctx->counter[i - 1] != 0 )
332 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000333
334 /*
335 * Crypt counter block
336 */
337 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, tmp );
338
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000339 use_len = (output_len > CTR_DRBG_BLOCKSIZE ) ? CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000340 /*
341 * Copy random block to destination
342 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000343 memcpy( p, tmp, use_len );
344 p += use_len;
345 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000346 }
347
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000348 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000349
350 ctx->reseed_counter++;
351
352 return( 0 );
353}
354
355int ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
356{
357 return ctr_drbg_random_with_add( p_rng, output, output_len, NULL, 0 );
358}
359
Paul Bakkerfc754a92011-12-05 13:23:51 +0000360#if defined(POLARSSL_FS_IO)
361int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path )
362{
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200363 int ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000364 FILE *f;
365 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
366
367 if( ( f = fopen( path, "wb" ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000368 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000369
370 if( ( ret = ctr_drbg_random( ctx, buf, CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200371 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000372
373 if( fwrite( buf, 1, CTR_DRBG_MAX_INPUT, f ) != CTR_DRBG_MAX_INPUT )
374 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100375 ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR;
376 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000377 }
378
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200379 ret = 0;
380
381exit:
Paul Bakkerfc754a92011-12-05 13:23:51 +0000382 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200383 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000384}
385
386int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path )
387{
388 FILE *f;
389 size_t n;
390 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
391
392 if( ( f = fopen( path, "rb" ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000393 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000394
395 fseek( f, 0, SEEK_END );
396 n = (size_t) ftell( f );
397 fseek( f, 0, SEEK_SET );
398
399 if( n > CTR_DRBG_MAX_INPUT )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200400 {
401 fclose( f );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000402 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200403 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000404
405 if( fread( buf, 1, n, f ) != n )
406 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100407 fclose( f );
408 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000409 }
410
Paul Bakkerfc754a92011-12-05 13:23:51 +0000411 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200412
413 ctr_drbg_update( ctx, buf, n );
414
Paul Bakkerfc754a92011-12-05 13:23:51 +0000415 return( ctr_drbg_write_seed_file( ctx, path ) );
416}
417#endif /* POLARSSL_FS_IO */
418
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000419#if defined(POLARSSL_SELF_TEST)
420
421#include <stdio.h>
422
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100423static unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000424 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
425 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
426 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
427 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
428 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
429 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
430 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
431 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
432 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
433 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
434 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
435 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
436
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100437static unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000438 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
439 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
440 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
441 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
442 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
443 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
444 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
445 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
446
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100447static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000448 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
449 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
450
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100451static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000452 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
453 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
454
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100455static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000456 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
457 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
458
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100459static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000460 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
461 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
462
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100463static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200464static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
465 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000466{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100467 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000468 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100469 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000470 return( 0 );
471}
472
Paul Bakker7dc4c442014-02-01 22:50:26 +0100473#define CHK( c ) if( (c) != 0 ) \
474 { \
475 if( verbose != 0 ) \
476 polarssl_printf( "failed\n" ); \
477 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100478 }
479
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000480/*
481 * Checkup routine
482 */
483int ctr_drbg_self_test( int verbose )
484{
485 ctr_drbg_context ctx;
486 unsigned char buf[16];
487
488 /*
489 * Based on a NIST CTR_DRBG test vector (PR = True)
490 */
491 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100492 polarssl_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000493
494 test_offset = 0;
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100495 CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
496 entropy_source_pr, nonce_pers_pr, 16, 32 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000497 ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100498 CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) );
499 CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) );
500 CHK( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000501
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000502 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100503 polarssl_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000504
505 /*
506 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
507 */
508 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100509 polarssl_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000510
511 test_offset = 0;
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100512 CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
513 entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
514 CHK( ctr_drbg_random( &ctx, buf, 16 ) );
515 CHK( ctr_drbg_reseed( &ctx, NULL, 0 ) );
516 CHK( ctr_drbg_random( &ctx, buf, 16 ) );
517 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000518
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000519 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100520 polarssl_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000521
522 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100523 polarssl_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000524
525 return( 0 );
526}
527#endif
528
529#endif