blob: 249b84069534db02e61e7d3148e8f3f4611a27c2 [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
Paul Bakkerc7ea99a2014-06-18 11:12:03 +020069 aes_init( &ctx->aes_ctx );
70
Paul Bakker0e04d0e2011-11-27 14:46:59 +000071 ctx->f_entropy = f_entropy;
72 ctx->p_entropy = p_entropy;
73
Paul Bakker18d32912011-12-10 21:42:49 +000074 ctx->entropy_len = entropy_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +000075 ctx->reseed_interval = CTR_DRBG_RESEED_INTERVAL;
76
77 /*
78 * Initialize with an empty key
79 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +000080 aes_setkey_enc( &ctx->aes_ctx, key, CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000081
82 if( ( ret = ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
83 return( ret );
84
85 return( 0 );
86}
87
Paul Bakker18d32912011-12-10 21:42:49 +000088int ctr_drbg_init( ctr_drbg_context *ctx,
89 int (*f_entropy)(void *, unsigned char *, size_t),
90 void *p_entropy,
91 const unsigned char *custom,
92 size_t len )
93{
94 return( ctr_drbg_init_entropy_len( ctx, f_entropy, p_entropy, custom, len,
95 CTR_DRBG_ENTROPY_LEN ) );
96}
97
Paul Bakker0e04d0e2011-11-27 14:46:59 +000098void ctr_drbg_set_prediction_resistance( ctr_drbg_context *ctx, int resistance )
99{
100 ctx->prediction_resistance = resistance;
101}
102
103void ctr_drbg_set_entropy_len( ctr_drbg_context *ctx, size_t len )
104{
105 ctx->entropy_len = len;
106}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200107
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000108void ctr_drbg_set_reseed_interval( ctr_drbg_context *ctx, int interval )
109{
110 ctx->reseed_interval = interval;
111}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200112
113static int block_cipher_df( unsigned char *output,
114 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000115{
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000116 unsigned char buf[CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000117 unsigned char tmp[CTR_DRBG_SEEDLEN];
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000118 unsigned char key[CTR_DRBG_KEYSIZE];
119 unsigned char chain[CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100120 unsigned char *p, *iv;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000121 aes_context aes_ctx;
122
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200123 int i, j;
124 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000125
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000126 memset( buf, 0, CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16 );
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200127 aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000128
129 /*
130 * Construct IV (16 bytes) and S in buffer
131 * IV = Counter (in 32-bits) padded to 16 with zeroes
132 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
133 * data || 0x80
134 * (Total is padded to a multiple of 16-bytes with zeroes)
135 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000136 p = buf + CTR_DRBG_BLOCKSIZE;
137 *p++ = ( data_len >> 24 ) & 0xff;
138 *p++ = ( data_len >> 16 ) & 0xff;
139 *p++ = ( data_len >> 8 ) & 0xff;
140 *p++ = ( data_len ) & 0xff;
141 p += 3;
142 *p++ = CTR_DRBG_SEEDLEN;
143 memcpy( p, data, data_len );
144 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000145
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000146 buf_len = CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000147
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000148 for( i = 0; i < CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000149 key[i] = i;
150
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000151 aes_setkey_enc( &aes_ctx, key, CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000152
153 /*
154 * Reduce data to POLARSSL_CTR_DRBG_SEEDLEN bytes of data
155 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000156 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000157 {
158 p = buf;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000159 memset( chain, 0, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000160 use_len = buf_len;
161
162 while( use_len > 0 )
163 {
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000164 for( i = 0; i < CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000165 chain[i] ^= p[i];
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000166 p += CTR_DRBG_BLOCKSIZE;
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200167 use_len -= ( use_len >= CTR_DRBG_BLOCKSIZE ) ?
168 CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000169
170 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, chain, chain );
171 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200172
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000173 memcpy( tmp + j, chain, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000174
175 /*
176 * Update IV
177 */
178 buf[3]++;
179 }
180
181 /*
182 * Do final encryption with reduced data
183 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000184 aes_setkey_enc( &aes_ctx, tmp, CTR_DRBG_KEYBITS );
185 iv = tmp + CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000186 p = output;
187
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000188 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000189 {
190 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, iv, iv );
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000191 memcpy( p, iv, CTR_DRBG_BLOCKSIZE );
192 p += CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000193 }
194
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200195 aes_free( &aes_ctx );
196
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000197 return( 0 );
198}
199
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200200static int ctr_drbg_update_internal( ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000201 const unsigned char data[CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000202{
203 unsigned char tmp[CTR_DRBG_SEEDLEN];
204 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000205 int i, j;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000206
207 memset( tmp, 0, CTR_DRBG_SEEDLEN );
208
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000209 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000210 {
211 /*
212 * Increase counter
213 */
Paul Bakker9a736322012-11-14 12:39:52 +0000214 for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000215 if( ++ctx->counter[i - 1] != 0 )
216 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000217
218 /*
219 * Crypt counter block
220 */
221 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, p );
222
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000223 p += CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000224 }
225
226 for( i = 0; i < CTR_DRBG_SEEDLEN; i++ )
227 tmp[i] ^= data[i];
228
229 /*
230 * Update key and counter
231 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000232 aes_setkey_enc( &ctx->aes_ctx, tmp, CTR_DRBG_KEYBITS );
233 memcpy( ctx->counter, tmp + CTR_DRBG_KEYSIZE, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000234
235 return( 0 );
236}
237
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000238void ctr_drbg_update( ctr_drbg_context *ctx,
239 const unsigned char *additional, size_t add_len )
240{
241 unsigned char add_input[CTR_DRBG_SEEDLEN];
242
243 if( add_len > 0 )
244 {
245 block_cipher_df( add_input, additional, add_len );
246 ctr_drbg_update_internal( ctx, add_input );
247 }
248}
249
250int ctr_drbg_reseed( ctr_drbg_context *ctx,
251 const unsigned char *additional, size_t len )
252{
253 unsigned char seed[CTR_DRBG_MAX_SEED_INPUT];
254 size_t seedlen = 0;
255
256 if( ctx->entropy_len + len > CTR_DRBG_MAX_SEED_INPUT )
257 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
258
259 memset( seed, 0, CTR_DRBG_MAX_SEED_INPUT );
260
261 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200262 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000263 */
264 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
265 ctx->entropy_len ) )
266 {
267 return( POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
268 }
269
270 seedlen += ctx->entropy_len;
271
272 /*
273 * Add additional data
274 */
275 if( additional && len )
276 {
277 memcpy( seed + seedlen, additional, len );
278 seedlen += len;
279 }
280
281 /*
282 * Reduce to 384 bits
283 */
284 block_cipher_df( seed, seed, seedlen );
285
286 /*
287 * Update state
288 */
289 ctr_drbg_update_internal( ctx, seed );
290 ctx->reseed_counter = 1;
291
292 return( 0 );
293}
Paul Bakker9af723c2014-05-01 13:03:14 +0200294
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000295int ctr_drbg_random_with_add( void *p_rng,
296 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000297 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000298{
299 int ret = 0;
300 ctr_drbg_context *ctx = (ctr_drbg_context *) p_rng;
301 unsigned char add_input[CTR_DRBG_SEEDLEN];
302 unsigned char *p = output;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000303 unsigned char tmp[CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000304 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000305 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000306
307 if( output_len > CTR_DRBG_MAX_REQUEST )
308 return( POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG );
309
310 if( add_len > CTR_DRBG_MAX_INPUT )
311 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
312
313 memset( add_input, 0, CTR_DRBG_SEEDLEN );
314
315 if( ctx->reseed_counter > ctx->reseed_interval ||
316 ctx->prediction_resistance )
317 {
318 if( ( ret = ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
319 return( ret );
320
321 add_len = 0;
322 }
323
324 if( add_len > 0 )
325 {
326 block_cipher_df( add_input, additional, add_len );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000327 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000328 }
329
330 while( output_len > 0 )
331 {
332 /*
333 * Increase counter
334 */
Paul Bakker369e14b2012-04-18 14:16:09 +0000335 for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
336 if( ++ctx->counter[i - 1] != 0 )
337 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000338
339 /*
340 * Crypt counter block
341 */
342 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, tmp );
343
Paul Bakker66d5d072014-06-17 16:39:18 +0200344 use_len = ( output_len > CTR_DRBG_BLOCKSIZE ) ? CTR_DRBG_BLOCKSIZE :
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200345 output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000346 /*
347 * Copy random block to destination
348 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000349 memcpy( p, tmp, use_len );
350 p += use_len;
351 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000352 }
353
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000354 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000355
356 ctx->reseed_counter++;
357
358 return( 0 );
359}
360
361int ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
362{
363 return ctr_drbg_random_with_add( p_rng, output, output_len, NULL, 0 );
364}
365
Paul Bakkerfc754a92011-12-05 13:23:51 +0000366#if defined(POLARSSL_FS_IO)
367int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path )
368{
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200369 int ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000370 FILE *f;
371 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
372
373 if( ( f = fopen( path, "wb" ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000374 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000375
376 if( ( ret = ctr_drbg_random( ctx, buf, CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200377 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000378
379 if( fwrite( buf, 1, CTR_DRBG_MAX_INPUT, f ) != CTR_DRBG_MAX_INPUT )
380 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100381 ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR;
382 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000383 }
384
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200385 ret = 0;
386
387exit:
Paul Bakkerfc754a92011-12-05 13:23:51 +0000388 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200389 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000390}
391
392int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path )
393{
394 FILE *f;
395 size_t n;
396 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
397
398 if( ( f = fopen( path, "rb" ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000399 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000400
401 fseek( f, 0, SEEK_END );
402 n = (size_t) ftell( f );
403 fseek( f, 0, SEEK_SET );
404
405 if( n > CTR_DRBG_MAX_INPUT )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200406 {
407 fclose( f );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000408 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200409 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000410
411 if( fread( buf, 1, n, f ) != n )
412 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100413 fclose( f );
414 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000415 }
416
Paul Bakkerfc754a92011-12-05 13:23:51 +0000417 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200418
419 ctr_drbg_update( ctx, buf, n );
420
Paul Bakkerfc754a92011-12-05 13:23:51 +0000421 return( ctr_drbg_write_seed_file( ctx, path ) );
422}
423#endif /* POLARSSL_FS_IO */
424
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000425#if defined(POLARSSL_SELF_TEST)
426
427#include <stdio.h>
428
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100429static unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000430 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
431 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
432 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
433 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
434 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
435 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
436 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
437 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
438 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
439 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
440 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
441 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
442
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100443static unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000444 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
445 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
446 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
447 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
448 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
449 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
450 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
451 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
452
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100453static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000454 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
455 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
456
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100457static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000458 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
459 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
460
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100461static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000462 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
463 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
464
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100465static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000466 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
467 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
468
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100469static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200470static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
471 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000472{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100473 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000474 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100475 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000476 return( 0 );
477}
478
Paul Bakker7dc4c442014-02-01 22:50:26 +0100479#define CHK( c ) if( (c) != 0 ) \
480 { \
481 if( verbose != 0 ) \
482 polarssl_printf( "failed\n" ); \
483 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100484 }
485
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000486/*
487 * Checkup routine
488 */
489int ctr_drbg_self_test( int verbose )
490{
491 ctr_drbg_context ctx;
492 unsigned char buf[16];
493
494 /*
495 * Based on a NIST CTR_DRBG test vector (PR = True)
496 */
497 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100498 polarssl_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000499
500 test_offset = 0;
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100501 CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
502 entropy_source_pr, nonce_pers_pr, 16, 32 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000503 ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100504 CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) );
505 CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) );
506 CHK( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000507
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000508 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100509 polarssl_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000510
511 /*
512 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
513 */
514 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100515 polarssl_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000516
517 test_offset = 0;
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100518 CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
519 entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
520 CHK( ctr_drbg_random( &ctx, buf, 16 ) );
521 CHK( ctr_drbg_reseed( &ctx, NULL, 0 ) );
522 CHK( ctr_drbg_random( &ctx, buf, 16 ) );
523 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000524
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000525 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100526 polarssl_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000527
528 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100529 polarssl_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000530
531 return( 0 );
532}
Paul Bakker9af723c2014-05-01 13:03:14 +0200533#endif /* POLARSSL_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000534
Paul Bakker9af723c2014-05-01 13:03:14 +0200535#endif /* POLARSSL_CTR_DRBG_C */