blob: 40278090932ef1fe2e7983c4b4c765e01f4a6bc6 [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
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 Bakker7dc4c442014-02-01 22:50:26 +010041#if defined(POLARSSL_PLATFORM_C)
42#include "polarssl/platform.h"
43#else
44#define polarssl_printf printf
45#endif
46
Paul Bakker18d32912011-12-10 21:42:49 +000047/*
48 * Non-public function wrapped by ctr_crbg_init(). Necessary to allow NIST
49 * tests to succeed (which require known length fixed entropy)
50 */
Paul Bakker534f82c2013-06-25 16:47:55 +020051int ctr_drbg_init_entropy_len(
Paul Bakker18d32912011-12-10 21:42:49 +000052 ctr_drbg_context *ctx,
Paul Bakker0e04d0e2011-11-27 14:46:59 +000053 int (*f_entropy)(void *, unsigned char *, size_t),
54 void *p_entropy,
Paul Bakker1bc9efc2011-12-03 11:29:32 +000055 const unsigned char *custom,
Paul Bakker18d32912011-12-10 21:42:49 +000056 size_t len,
57 size_t entropy_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000058{
59 int ret;
Paul Bakker2bc7cf12011-11-29 10:50:51 +000060 unsigned char key[CTR_DRBG_KEYSIZE];
Paul Bakker0e04d0e2011-11-27 14:46:59 +000061
62 memset( ctx, 0, sizeof(ctr_drbg_context) );
Paul Bakker2bc7cf12011-11-29 10:50:51 +000063 memset( key, 0, CTR_DRBG_KEYSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000064
65 ctx->f_entropy = f_entropy;
66 ctx->p_entropy = p_entropy;
67
Paul Bakker18d32912011-12-10 21:42:49 +000068 ctx->entropy_len = entropy_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +000069 ctx->reseed_interval = CTR_DRBG_RESEED_INTERVAL;
70
71 /*
72 * Initialize with an empty key
73 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +000074 aes_setkey_enc( &ctx->aes_ctx, key, CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000075
76 if( ( ret = ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
77 return( ret );
78
79 return( 0 );
80}
81
Paul Bakker18d32912011-12-10 21:42:49 +000082int ctr_drbg_init( ctr_drbg_context *ctx,
83 int (*f_entropy)(void *, unsigned char *, size_t),
84 void *p_entropy,
85 const unsigned char *custom,
86 size_t len )
87{
88 return( ctr_drbg_init_entropy_len( ctx, f_entropy, p_entropy, custom, len,
89 CTR_DRBG_ENTROPY_LEN ) );
90}
91
Paul Bakker0e04d0e2011-11-27 14:46:59 +000092void ctr_drbg_set_prediction_resistance( ctr_drbg_context *ctx, int resistance )
93{
94 ctx->prediction_resistance = resistance;
95}
96
97void ctr_drbg_set_entropy_len( ctr_drbg_context *ctx, size_t len )
98{
99 ctx->entropy_len = len;
100}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200101
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000102void ctr_drbg_set_reseed_interval( ctr_drbg_context *ctx, int interval )
103{
104 ctx->reseed_interval = interval;
105}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200106
107static int block_cipher_df( unsigned char *output,
108 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000109{
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000110 unsigned char buf[CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000111 unsigned char tmp[CTR_DRBG_SEEDLEN];
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000112 unsigned char key[CTR_DRBG_KEYSIZE];
113 unsigned char chain[CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100114 unsigned char *p, *iv;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000115 aes_context aes_ctx;
116
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200117 int i, j;
118 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000119
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000120 memset( buf, 0, CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16 );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000121
122 /*
123 * Construct IV (16 bytes) and S in buffer
124 * IV = Counter (in 32-bits) padded to 16 with zeroes
125 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
126 * data || 0x80
127 * (Total is padded to a multiple of 16-bytes with zeroes)
128 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000129 p = buf + CTR_DRBG_BLOCKSIZE;
130 *p++ = ( data_len >> 24 ) & 0xff;
131 *p++ = ( data_len >> 16 ) & 0xff;
132 *p++ = ( data_len >> 8 ) & 0xff;
133 *p++ = ( data_len ) & 0xff;
134 p += 3;
135 *p++ = CTR_DRBG_SEEDLEN;
136 memcpy( p, data, data_len );
137 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000138
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000139 buf_len = CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000140
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000141 for( i = 0; i < CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000142 key[i] = i;
143
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000144 aes_setkey_enc( &aes_ctx, key, CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000145
146 /*
147 * Reduce data to POLARSSL_CTR_DRBG_SEEDLEN bytes of data
148 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000149 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000150 {
151 p = buf;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000152 memset( chain, 0, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000153 use_len = buf_len;
154
155 while( use_len > 0 )
156 {
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000157 for( i = 0; i < CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000158 chain[i] ^= p[i];
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000159 p += CTR_DRBG_BLOCKSIZE;
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200160 use_len -= ( use_len >= CTR_DRBG_BLOCKSIZE ) ?
161 CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000162
163 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, chain, chain );
164 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200165
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 Bakkerb6c5d2e2013-06-25 16:25:17 +0200191static int ctr_drbg_update_internal( ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000192 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 {
236 block_cipher_df( add_input, additional, add_len );
237 ctr_drbg_update_internal( ctx, add_input );
238 }
239}
240
241int ctr_drbg_reseed( ctr_drbg_context *ctx,
242 const unsigned char *additional, size_t len )
243{
244 unsigned char seed[CTR_DRBG_MAX_SEED_INPUT];
245 size_t seedlen = 0;
246
247 if( ctx->entropy_len + len > CTR_DRBG_MAX_SEED_INPUT )
248 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
249
250 memset( seed, 0, CTR_DRBG_MAX_SEED_INPUT );
251
252 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200253 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000254 */
255 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
256 ctx->entropy_len ) )
257 {
258 return( POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
259 }
260
261 seedlen += ctx->entropy_len;
262
263 /*
264 * Add additional data
265 */
266 if( additional && len )
267 {
268 memcpy( seed + seedlen, additional, len );
269 seedlen += len;
270 }
271
272 /*
273 * Reduce to 384 bits
274 */
275 block_cipher_df( seed, seed, seedlen );
276
277 /*
278 * Update state
279 */
280 ctr_drbg_update_internal( ctx, seed );
281 ctx->reseed_counter = 1;
282
283 return( 0 );
284}
285
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000286int ctr_drbg_random_with_add( void *p_rng,
287 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000288 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000289{
290 int ret = 0;
291 ctr_drbg_context *ctx = (ctr_drbg_context *) p_rng;
292 unsigned char add_input[CTR_DRBG_SEEDLEN];
293 unsigned char *p = output;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000294 unsigned char tmp[CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000295 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000296 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000297
298 if( output_len > CTR_DRBG_MAX_REQUEST )
299 return( POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG );
300
301 if( add_len > CTR_DRBG_MAX_INPUT )
302 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
303
304 memset( add_input, 0, CTR_DRBG_SEEDLEN );
305
306 if( ctx->reseed_counter > ctx->reseed_interval ||
307 ctx->prediction_resistance )
308 {
309 if( ( ret = ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
310 return( ret );
311
312 add_len = 0;
313 }
314
315 if( add_len > 0 )
316 {
317 block_cipher_df( add_input, additional, add_len );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000318 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000319 }
320
321 while( output_len > 0 )
322 {
323 /*
324 * Increase counter
325 */
Paul Bakker369e14b2012-04-18 14:16:09 +0000326 for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
327 if( ++ctx->counter[i - 1] != 0 )
328 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000329
330 /*
331 * Crypt counter block
332 */
333 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, tmp );
334
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000335 use_len = (output_len > CTR_DRBG_BLOCKSIZE ) ? CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000336 /*
337 * Copy random block to destination
338 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000339 memcpy( p, tmp, use_len );
340 p += use_len;
341 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000342 }
343
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000344 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000345
346 ctx->reseed_counter++;
347
348 return( 0 );
349}
350
351int ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
352{
353 return ctr_drbg_random_with_add( p_rng, output, output_len, NULL, 0 );
354}
355
Paul Bakkerfc754a92011-12-05 13:23:51 +0000356#if defined(POLARSSL_FS_IO)
357int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path )
358{
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200359 int ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000360 FILE *f;
361 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
362
363 if( ( f = fopen( path, "wb" ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000364 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000365
366 if( ( ret = ctr_drbg_random( ctx, buf, CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200367 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000368
369 if( fwrite( buf, 1, CTR_DRBG_MAX_INPUT, f ) != CTR_DRBG_MAX_INPUT )
370 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100371 ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR;
372 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000373 }
374
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200375 ret = 0;
376
377exit:
Paul Bakkerfc754a92011-12-05 13:23:51 +0000378 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200379 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000380}
381
382int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path )
383{
384 FILE *f;
385 size_t n;
386 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
387
388 if( ( f = fopen( path, "rb" ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000389 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000390
391 fseek( f, 0, SEEK_END );
392 n = (size_t) ftell( f );
393 fseek( f, 0, SEEK_SET );
394
395 if( n > CTR_DRBG_MAX_INPUT )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200396 {
397 fclose( f );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000398 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200399 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000400
401 if( fread( buf, 1, n, f ) != n )
402 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100403 fclose( f );
404 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000405 }
406
Paul Bakkerfc754a92011-12-05 13:23:51 +0000407 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200408
409 ctr_drbg_update( ctx, buf, n );
410
Paul Bakkerfc754a92011-12-05 13:23:51 +0000411 return( ctr_drbg_write_seed_file( ctx, path ) );
412}
413#endif /* POLARSSL_FS_IO */
414
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000415#if defined(POLARSSL_SELF_TEST)
416
417#include <stdio.h>
418
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100419static unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000420 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
421 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
422 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
423 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
424 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
425 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
426 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
427 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
428 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
429 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
430 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
431 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
432
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100433static unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000434 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
435 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
436 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
437 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
438 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
439 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
440 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
441 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
442
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100443static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000444 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
445 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
446
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100447static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000448 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
449 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
450
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100451static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000452 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
453 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
454
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100455static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000456 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
457 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
458
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100459static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200460static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
461 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000462{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100463 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000464 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100465 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000466 return( 0 );
467}
468
Paul Bakker7dc4c442014-02-01 22:50:26 +0100469#define CHK( c ) if( (c) != 0 ) \
470 { \
471 if( verbose != 0 ) \
472 polarssl_printf( "failed\n" ); \
473 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100474 }
475
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000476/*
477 * Checkup routine
478 */
479int ctr_drbg_self_test( int verbose )
480{
481 ctr_drbg_context ctx;
482 unsigned char buf[16];
483
484 /*
485 * Based on a NIST CTR_DRBG test vector (PR = True)
486 */
487 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100488 polarssl_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000489
490 test_offset = 0;
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100491 CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
492 entropy_source_pr, nonce_pers_pr, 16, 32 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000493 ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100494 CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) );
495 CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) );
496 CHK( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000497
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000498 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100499 polarssl_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000500
501 /*
502 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
503 */
504 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100505 polarssl_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000506
507 test_offset = 0;
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100508 CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
509 entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
510 CHK( ctr_drbg_random( &ctx, buf, 16 ) );
511 CHK( ctr_drbg_reseed( &ctx, NULL, 0 ) );
512 CHK( ctr_drbg_random( &ctx, buf, 16 ) );
513 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000514
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000515 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100516 polarssl_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000517
518 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100519 polarssl_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000520
521 return( 0 );
522}
523#endif
524
525#endif