blob: 96ee4f1625012d388cb2fd9ce4c2433ea96f08a7 [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 Bakkerfff03662014-06-18 16:21:25 +020051/* Implementation that should never be optimized out by the compiler */
52static void polarssl_zeroize( void *v, size_t n ) {
53 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
54}
55
Paul Bakker18d32912011-12-10 21:42:49 +000056/*
57 * Non-public function wrapped by ctr_crbg_init(). Necessary to allow NIST
58 * tests to succeed (which require known length fixed entropy)
59 */
Paul Bakker534f82c2013-06-25 16:47:55 +020060int ctr_drbg_init_entropy_len(
Paul Bakker18d32912011-12-10 21:42:49 +000061 ctr_drbg_context *ctx,
Paul Bakker0e04d0e2011-11-27 14:46:59 +000062 int (*f_entropy)(void *, unsigned char *, size_t),
63 void *p_entropy,
Paul Bakker1bc9efc2011-12-03 11:29:32 +000064 const unsigned char *custom,
Paul Bakker18d32912011-12-10 21:42:49 +000065 size_t len,
66 size_t entropy_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000067{
68 int ret;
Paul Bakker2bc7cf12011-11-29 10:50:51 +000069 unsigned char key[CTR_DRBG_KEYSIZE];
Paul Bakker0e04d0e2011-11-27 14:46:59 +000070
71 memset( ctx, 0, sizeof(ctr_drbg_context) );
Paul Bakker2bc7cf12011-11-29 10:50:51 +000072 memset( key, 0, CTR_DRBG_KEYSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000073
Paul Bakkerc7ea99a2014-06-18 11:12:03 +020074 aes_init( &ctx->aes_ctx );
75
Paul Bakker0e04d0e2011-11-27 14:46:59 +000076 ctx->f_entropy = f_entropy;
77 ctx->p_entropy = p_entropy;
78
Paul Bakker18d32912011-12-10 21:42:49 +000079 ctx->entropy_len = entropy_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +000080 ctx->reseed_interval = CTR_DRBG_RESEED_INTERVAL;
81
82 /*
83 * Initialize with an empty key
84 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +000085 aes_setkey_enc( &ctx->aes_ctx, key, CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000086
87 if( ( ret = ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
88 return( ret );
89
90 return( 0 );
91}
92
Paul Bakker18d32912011-12-10 21:42:49 +000093int ctr_drbg_init( ctr_drbg_context *ctx,
94 int (*f_entropy)(void *, unsigned char *, size_t),
95 void *p_entropy,
96 const unsigned char *custom,
97 size_t len )
98{
99 return( ctr_drbg_init_entropy_len( ctx, f_entropy, p_entropy, custom, len,
100 CTR_DRBG_ENTROPY_LEN ) );
101}
102
Paul Bakkerfff03662014-06-18 16:21:25 +0200103void ctr_drbg_free( ctr_drbg_context *ctx )
104{
105 if( ctx == NULL )
106 return;
107
108 aes_free( &ctx->aes_ctx );
109 polarssl_zeroize( ctx, sizeof( ctr_drbg_context ) );
110}
111
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000112void ctr_drbg_set_prediction_resistance( ctr_drbg_context *ctx, int resistance )
113{
114 ctx->prediction_resistance = resistance;
115}
116
117void ctr_drbg_set_entropy_len( ctr_drbg_context *ctx, size_t len )
118{
119 ctx->entropy_len = len;
120}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200121
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000122void ctr_drbg_set_reseed_interval( ctr_drbg_context *ctx, int interval )
123{
124 ctx->reseed_interval = interval;
125}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200126
127static int block_cipher_df( unsigned char *output,
128 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000129{
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000130 unsigned char buf[CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000131 unsigned char tmp[CTR_DRBG_SEEDLEN];
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000132 unsigned char key[CTR_DRBG_KEYSIZE];
133 unsigned char chain[CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100134 unsigned char *p, *iv;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000135 aes_context aes_ctx;
136
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200137 int i, j;
138 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000139
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000140 memset( buf, 0, CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16 );
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200141 aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000142
143 /*
144 * Construct IV (16 bytes) and S in buffer
145 * IV = Counter (in 32-bits) padded to 16 with zeroes
146 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
147 * data || 0x80
148 * (Total is padded to a multiple of 16-bytes with zeroes)
149 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000150 p = buf + CTR_DRBG_BLOCKSIZE;
151 *p++ = ( data_len >> 24 ) & 0xff;
152 *p++ = ( data_len >> 16 ) & 0xff;
153 *p++ = ( data_len >> 8 ) & 0xff;
154 *p++ = ( data_len ) & 0xff;
155 p += 3;
156 *p++ = CTR_DRBG_SEEDLEN;
157 memcpy( p, data, data_len );
158 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000159
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000160 buf_len = CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000161
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000162 for( i = 0; i < CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000163 key[i] = i;
164
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000165 aes_setkey_enc( &aes_ctx, key, CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000166
167 /*
168 * Reduce data to POLARSSL_CTR_DRBG_SEEDLEN bytes of data
169 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000170 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000171 {
172 p = buf;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000173 memset( chain, 0, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000174 use_len = buf_len;
175
176 while( use_len > 0 )
177 {
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000178 for( i = 0; i < CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000179 chain[i] ^= p[i];
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000180 p += CTR_DRBG_BLOCKSIZE;
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200181 use_len -= ( use_len >= CTR_DRBG_BLOCKSIZE ) ?
182 CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000183
184 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, chain, chain );
185 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200186
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000187 memcpy( tmp + j, chain, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000188
189 /*
190 * Update IV
191 */
192 buf[3]++;
193 }
194
195 /*
196 * Do final encryption with reduced data
197 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000198 aes_setkey_enc( &aes_ctx, tmp, CTR_DRBG_KEYBITS );
199 iv = tmp + CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000200 p = output;
201
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000202 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000203 {
204 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, iv, iv );
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000205 memcpy( p, iv, CTR_DRBG_BLOCKSIZE );
206 p += CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000207 }
208
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200209 aes_free( &aes_ctx );
210
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000211 return( 0 );
212}
213
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200214static int ctr_drbg_update_internal( ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000215 const unsigned char data[CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000216{
217 unsigned char tmp[CTR_DRBG_SEEDLEN];
218 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000219 int i, j;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000220
221 memset( tmp, 0, CTR_DRBG_SEEDLEN );
222
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000223 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000224 {
225 /*
226 * Increase counter
227 */
Paul Bakker9a736322012-11-14 12:39:52 +0000228 for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000229 if( ++ctx->counter[i - 1] != 0 )
230 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000231
232 /*
233 * Crypt counter block
234 */
235 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, p );
236
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000237 p += CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000238 }
239
240 for( i = 0; i < CTR_DRBG_SEEDLEN; i++ )
241 tmp[i] ^= data[i];
242
243 /*
244 * Update key and counter
245 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000246 aes_setkey_enc( &ctx->aes_ctx, tmp, CTR_DRBG_KEYBITS );
247 memcpy( ctx->counter, tmp + CTR_DRBG_KEYSIZE, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000248
249 return( 0 );
250}
251
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000252void ctr_drbg_update( ctr_drbg_context *ctx,
253 const unsigned char *additional, size_t add_len )
254{
255 unsigned char add_input[CTR_DRBG_SEEDLEN];
256
257 if( add_len > 0 )
258 {
259 block_cipher_df( add_input, additional, add_len );
260 ctr_drbg_update_internal( ctx, add_input );
261 }
262}
263
264int ctr_drbg_reseed( ctr_drbg_context *ctx,
265 const unsigned char *additional, size_t len )
266{
267 unsigned char seed[CTR_DRBG_MAX_SEED_INPUT];
268 size_t seedlen = 0;
269
270 if( ctx->entropy_len + len > CTR_DRBG_MAX_SEED_INPUT )
271 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
272
273 memset( seed, 0, CTR_DRBG_MAX_SEED_INPUT );
274
275 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200276 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000277 */
278 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
279 ctx->entropy_len ) )
280 {
281 return( POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
282 }
283
284 seedlen += ctx->entropy_len;
285
286 /*
287 * Add additional data
288 */
289 if( additional && len )
290 {
291 memcpy( seed + seedlen, additional, len );
292 seedlen += len;
293 }
294
295 /*
296 * Reduce to 384 bits
297 */
298 block_cipher_df( seed, seed, seedlen );
299
300 /*
301 * Update state
302 */
303 ctr_drbg_update_internal( ctx, seed );
304 ctx->reseed_counter = 1;
305
306 return( 0 );
307}
Paul Bakker9af723c2014-05-01 13:03:14 +0200308
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000309int ctr_drbg_random_with_add( void *p_rng,
310 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000311 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000312{
313 int ret = 0;
314 ctr_drbg_context *ctx = (ctr_drbg_context *) p_rng;
315 unsigned char add_input[CTR_DRBG_SEEDLEN];
316 unsigned char *p = output;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000317 unsigned char tmp[CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000318 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000319 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000320
321 if( output_len > CTR_DRBG_MAX_REQUEST )
322 return( POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG );
323
324 if( add_len > CTR_DRBG_MAX_INPUT )
325 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
326
327 memset( add_input, 0, CTR_DRBG_SEEDLEN );
328
329 if( ctx->reseed_counter > ctx->reseed_interval ||
330 ctx->prediction_resistance )
331 {
332 if( ( ret = ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
333 return( ret );
334
335 add_len = 0;
336 }
337
338 if( add_len > 0 )
339 {
340 block_cipher_df( add_input, additional, add_len );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000341 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000342 }
343
344 while( output_len > 0 )
345 {
346 /*
347 * Increase counter
348 */
Paul Bakker369e14b2012-04-18 14:16:09 +0000349 for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
350 if( ++ctx->counter[i - 1] != 0 )
351 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000352
353 /*
354 * Crypt counter block
355 */
356 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, tmp );
357
Paul Bakker66d5d072014-06-17 16:39:18 +0200358 use_len = ( output_len > CTR_DRBG_BLOCKSIZE ) ? CTR_DRBG_BLOCKSIZE :
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200359 output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000360 /*
361 * Copy random block to destination
362 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000363 memcpy( p, tmp, use_len );
364 p += use_len;
365 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000366 }
367
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000368 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000369
370 ctx->reseed_counter++;
371
372 return( 0 );
373}
374
375int ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
376{
377 return ctr_drbg_random_with_add( p_rng, output, output_len, NULL, 0 );
378}
379
Paul Bakkerfc754a92011-12-05 13:23:51 +0000380#if defined(POLARSSL_FS_IO)
381int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path )
382{
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200383 int ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000384 FILE *f;
385 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
386
387 if( ( f = fopen( path, "wb" ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000388 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000389
390 if( ( ret = ctr_drbg_random( ctx, buf, CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200391 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000392
393 if( fwrite( buf, 1, CTR_DRBG_MAX_INPUT, f ) != CTR_DRBG_MAX_INPUT )
394 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100395 ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR;
396 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000397 }
398
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200399 ret = 0;
400
401exit:
Paul Bakkerfc754a92011-12-05 13:23:51 +0000402 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200403 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000404}
405
406int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path )
407{
408 FILE *f;
409 size_t n;
410 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
411
412 if( ( f = fopen( path, "rb" ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000413 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000414
415 fseek( f, 0, SEEK_END );
416 n = (size_t) ftell( f );
417 fseek( f, 0, SEEK_SET );
418
419 if( n > CTR_DRBG_MAX_INPUT )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200420 {
421 fclose( f );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000422 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200423 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000424
425 if( fread( buf, 1, n, f ) != n )
426 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100427 fclose( f );
428 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000429 }
430
Paul Bakkerfc754a92011-12-05 13:23:51 +0000431 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200432
433 ctr_drbg_update( ctx, buf, n );
434
Paul Bakkerfc754a92011-12-05 13:23:51 +0000435 return( ctr_drbg_write_seed_file( ctx, path ) );
436}
437#endif /* POLARSSL_FS_IO */
438
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000439#if defined(POLARSSL_SELF_TEST)
440
441#include <stdio.h>
442
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100443static unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000444 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
445 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
446 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
447 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
448 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
449 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
450 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
451 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
452 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
453 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
454 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
455 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
456
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100457static unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000458 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
459 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
460 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
461 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
462 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
463 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
464 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
465 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
466
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100467static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000468 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
469 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
470
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100471static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000472 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
473 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
474
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100475static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000476 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
477 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
478
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100479static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000480 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
481 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
482
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100483static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200484static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
485 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000486{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100487 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000488 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100489 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000490 return( 0 );
491}
492
Paul Bakker7dc4c442014-02-01 22:50:26 +0100493#define CHK( c ) if( (c) != 0 ) \
494 { \
495 if( verbose != 0 ) \
496 polarssl_printf( "failed\n" ); \
497 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100498 }
499
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000500/*
501 * Checkup routine
502 */
503int ctr_drbg_self_test( int verbose )
504{
505 ctr_drbg_context ctx;
506 unsigned char buf[16];
507
508 /*
509 * Based on a NIST CTR_DRBG test vector (PR = True)
510 */
511 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100512 polarssl_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000513
514 test_offset = 0;
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100515 CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
516 entropy_source_pr, nonce_pers_pr, 16, 32 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000517 ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100518 CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) );
519 CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) );
520 CHK( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000521
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000522 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100523 polarssl_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000524
525 /*
526 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
527 */
528 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100529 polarssl_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000530
531 test_offset = 0;
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100532 CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
533 entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
534 CHK( ctr_drbg_random( &ctx, buf, 16 ) );
535 CHK( ctr_drbg_reseed( &ctx, NULL, 0 ) );
536 CHK( ctr_drbg_random( &ctx, buf, 16 ) );
537 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000538
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000539 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100540 polarssl_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000541
542 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100543 polarssl_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000544
545 return( 0 );
546}
Paul Bakker9af723c2014-05-01 13:03:14 +0200547#endif /* POLARSSL_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000548
Paul Bakker9af723c2014-05-01 13:03:14 +0200549#endif /* POLARSSL_CTR_DRBG_C */