blob: 3db517d551cd7332b1d21682b1c2ed3bb73c22df [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}
Paul Bakker9af723c2014-05-01 13:03:14 +0200289
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 Bakker66d5d072014-06-17 16:39:18 +0200339 use_len = ( output_len > CTR_DRBG_BLOCKSIZE ) ? CTR_DRBG_BLOCKSIZE :
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200340 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{
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200364 int ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000365 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 Bakkerc72d3f72013-05-14 13:22:41 +0200372 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000373
374 if( fwrite( buf, 1, CTR_DRBG_MAX_INPUT, f ) != CTR_DRBG_MAX_INPUT )
375 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100376 ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR;
377 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000378 }
379
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200380 ret = 0;
381
382exit:
Paul Bakkerfc754a92011-12-05 13:23:51 +0000383 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200384 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000385}
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 Bakkerc72d3f72013-05-14 13:22:41 +0200401 {
402 fclose( f );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000403 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200404 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000405
406 if( fread( buf, 1, n, f ) != n )
407 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100408 fclose( f );
409 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000410 }
411
Paul Bakkerfc754a92011-12-05 13:23:51 +0000412 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200413
414 ctr_drbg_update( ctx, buf, n );
415
Paul Bakkerfc754a92011-12-05 13:23:51 +0000416 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
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100424static unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000425 { 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
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100438static unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000439 { 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
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100448static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000449 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
450 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
451
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100452static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000453 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
454 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
455
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100456static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000457 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
458 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
459
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100460static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000461 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
462 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
463
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100464static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200465static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
466 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000467{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100468 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000469 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100470 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000471 return( 0 );
472}
473
Paul Bakker7dc4c442014-02-01 22:50:26 +0100474#define CHK( c ) if( (c) != 0 ) \
475 { \
476 if( verbose != 0 ) \
477 polarssl_printf( "failed\n" ); \
478 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100479 }
480
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000481/*
482 * Checkup routine
483 */
484int ctr_drbg_self_test( int verbose )
485{
486 ctr_drbg_context ctx;
487 unsigned char buf[16];
488
489 /*
490 * Based on a NIST CTR_DRBG test vector (PR = True)
491 */
492 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100493 polarssl_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000494
495 test_offset = 0;
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100496 CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
497 entropy_source_pr, nonce_pers_pr, 16, 32 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000498 ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100499 CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) );
500 CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) );
501 CHK( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000502
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000503 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100504 polarssl_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000505
506 /*
507 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
508 */
509 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100510 polarssl_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000511
512 test_offset = 0;
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100513 CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
514 entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
515 CHK( ctr_drbg_random( &ctx, buf, 16 ) );
516 CHK( ctr_drbg_reseed( &ctx, NULL, 0 ) );
517 CHK( ctr_drbg_random( &ctx, buf, 16 ) );
518 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000519
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000520 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100521 polarssl_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000522
523 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100524 polarssl_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000525
526 return( 0 );
527}
Paul Bakker9af723c2014-05-01 13:03:14 +0200528#endif /* POLARSSL_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000529
Paul Bakker9af723c2014-05-01 13:03:14 +0200530#endif /* POLARSSL_CTR_DRBG_C */