blob: aec29b9e63ace7dbf43198df8f3f426440157746 [file] [log] [blame]
Paul Bakker0e04d0e2011-11-27 14:46:59 +00001/*
2 * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
3 *
4 * Copyright (C) 2006-2011, Brainspark B.V.
5 *
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 Bakker18d32912011-12-10 21:42:49 +000041/*
42 * Non-public function wrapped by ctr_crbg_init(). Necessary to allow NIST
43 * tests to succeed (which require known length fixed entropy)
44 */
45int ctr_drbg_init_entropy_len(
46 ctr_drbg_context *ctx,
Paul Bakker0e04d0e2011-11-27 14:46:59 +000047 int (*f_entropy)(void *, unsigned char *, size_t),
48 void *p_entropy,
Paul Bakker1bc9efc2011-12-03 11:29:32 +000049 const unsigned char *custom,
Paul Bakker18d32912011-12-10 21:42:49 +000050 size_t len,
51 size_t entropy_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000052{
53 int ret;
Paul Bakker2bc7cf12011-11-29 10:50:51 +000054 unsigned char key[CTR_DRBG_KEYSIZE];
Paul Bakker0e04d0e2011-11-27 14:46:59 +000055
56 memset( ctx, 0, sizeof(ctr_drbg_context) );
Paul Bakker2bc7cf12011-11-29 10:50:51 +000057 memset( key, 0, CTR_DRBG_KEYSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000058
59 ctx->f_entropy = f_entropy;
60 ctx->p_entropy = p_entropy;
61
Paul Bakker18d32912011-12-10 21:42:49 +000062 ctx->entropy_len = entropy_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +000063 ctx->reseed_interval = CTR_DRBG_RESEED_INTERVAL;
64
65 /*
66 * Initialize with an empty key
67 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +000068 aes_setkey_enc( &ctx->aes_ctx, key, CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000069
70 if( ( ret = ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
71 return( ret );
72
73 return( 0 );
74}
75
Paul Bakker18d32912011-12-10 21:42:49 +000076int ctr_drbg_init( ctr_drbg_context *ctx,
77 int (*f_entropy)(void *, unsigned char *, size_t),
78 void *p_entropy,
79 const unsigned char *custom,
80 size_t len )
81{
82 return( ctr_drbg_init_entropy_len( ctx, f_entropy, p_entropy, custom, len,
83 CTR_DRBG_ENTROPY_LEN ) );
84}
85
Paul Bakker0e04d0e2011-11-27 14:46:59 +000086void ctr_drbg_set_prediction_resistance( ctr_drbg_context *ctx, int resistance )
87{
88 ctx->prediction_resistance = resistance;
89}
90
91void ctr_drbg_set_entropy_len( ctr_drbg_context *ctx, size_t len )
92{
93 ctx->entropy_len = len;
94}
95
96void ctr_drbg_set_reseed_interval( ctr_drbg_context *ctx, int interval )
97{
98 ctx->reseed_interval = interval;
99}
100
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000101int block_cipher_df( unsigned char *output,
102 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000103{
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000104 unsigned char buf[CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000105 unsigned char tmp[CTR_DRBG_SEEDLEN];
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000106 unsigned char key[CTR_DRBG_KEYSIZE];
107 unsigned char chain[CTR_DRBG_BLOCKSIZE];
Paul Bakker78370262014-07-07 16:00:26 +0200108 unsigned char *p, *iv;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000109 aes_context aes_ctx;
110
111 int i, j, buf_len, use_len;
112
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000113 memset( buf, 0, CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16 );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000114
115 /*
116 * Construct IV (16 bytes) and S in buffer
117 * IV = Counter (in 32-bits) padded to 16 with zeroes
118 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
119 * data || 0x80
120 * (Total is padded to a multiple of 16-bytes with zeroes)
121 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000122 p = buf + CTR_DRBG_BLOCKSIZE;
123 *p++ = ( data_len >> 24 ) & 0xff;
124 *p++ = ( data_len >> 16 ) & 0xff;
125 *p++ = ( data_len >> 8 ) & 0xff;
126 *p++ = ( data_len ) & 0xff;
127 p += 3;
128 *p++ = CTR_DRBG_SEEDLEN;
129 memcpy( p, data, data_len );
130 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000131
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000132 buf_len = CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000133
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000134 for( i = 0; i < CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000135 key[i] = i;
136
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000137 aes_setkey_enc( &aes_ctx, key, CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000138
139 /*
140 * Reduce data to POLARSSL_CTR_DRBG_SEEDLEN bytes of data
141 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000142 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000143 {
144 p = buf;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000145 memset( chain, 0, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000146 use_len = buf_len;
147
148 while( use_len > 0 )
149 {
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000150 for( i = 0; i < CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000151 chain[i] ^= p[i];
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000152 p += CTR_DRBG_BLOCKSIZE;
153 use_len -= CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000154
155 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, chain, chain );
156 }
157
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000158 memcpy( tmp + j, chain, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000159
160 /*
161 * Update IV
162 */
163 buf[3]++;
164 }
165
166 /*
167 * Do final encryption with reduced data
168 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000169 aes_setkey_enc( &aes_ctx, tmp, CTR_DRBG_KEYBITS );
170 iv = tmp + CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000171 p = output;
172
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000173 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000174 {
175 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, iv, iv );
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000176 memcpy( p, iv, CTR_DRBG_BLOCKSIZE );
177 p += CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000178 }
179
180 return( 0 );
181}
182
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000183int ctr_drbg_update_internal( ctr_drbg_context *ctx,
184 const unsigned char data[CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000185{
186 unsigned char tmp[CTR_DRBG_SEEDLEN];
187 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000188 int i, j;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000189
190 memset( tmp, 0, CTR_DRBG_SEEDLEN );
191
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000192 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000193 {
194 /*
195 * Increase counter
196 */
Paul Bakker9a736322012-11-14 12:39:52 +0000197 for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000198 if( ++ctx->counter[i - 1] != 0 )
199 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000200
201 /*
202 * Crypt counter block
203 */
204 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, p );
205
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000206 p += CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000207 }
208
209 for( i = 0; i < CTR_DRBG_SEEDLEN; i++ )
210 tmp[i] ^= data[i];
211
212 /*
213 * Update key and counter
214 */
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000215 aes_setkey_enc( &ctx->aes_ctx, tmp, CTR_DRBG_KEYBITS );
216 memcpy( ctx->counter, tmp + CTR_DRBG_KEYSIZE, CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000217
218 return( 0 );
219}
220
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000221void ctr_drbg_update( ctr_drbg_context *ctx,
222 const unsigned char *additional, size_t add_len )
223{
224 unsigned char add_input[CTR_DRBG_SEEDLEN];
225
226 if( add_len > 0 )
227 {
228 block_cipher_df( add_input, additional, add_len );
229 ctr_drbg_update_internal( ctx, add_input );
230 }
231}
232
233int ctr_drbg_reseed( ctr_drbg_context *ctx,
234 const unsigned char *additional, size_t len )
235{
236 unsigned char seed[CTR_DRBG_MAX_SEED_INPUT];
237 size_t seedlen = 0;
238
239 if( ctx->entropy_len + len > CTR_DRBG_MAX_SEED_INPUT )
240 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
241
242 memset( seed, 0, CTR_DRBG_MAX_SEED_INPUT );
243
244 /*
Paul Bakker69e095c2011-12-10 21:55:01 +0000245 * Gather enropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000246 */
247 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
248 ctx->entropy_len ) )
249 {
250 return( POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
251 }
252
253 seedlen += ctx->entropy_len;
254
255 /*
256 * Add additional data
257 */
258 if( additional && len )
259 {
260 memcpy( seed + seedlen, additional, len );
261 seedlen += len;
262 }
263
264 /*
265 * Reduce to 384 bits
266 */
267 block_cipher_df( seed, seed, seedlen );
268
269 /*
270 * Update state
271 */
272 ctr_drbg_update_internal( ctx, seed );
273 ctx->reseed_counter = 1;
274
275 return( 0 );
276}
277
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000278int ctr_drbg_random_with_add( void *p_rng,
279 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000280 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000281{
282 int ret = 0;
283 ctr_drbg_context *ctx = (ctr_drbg_context *) p_rng;
284 unsigned char add_input[CTR_DRBG_SEEDLEN];
285 unsigned char *p = output;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000286 unsigned char tmp[CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000287 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000288 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000289
290 if( output_len > CTR_DRBG_MAX_REQUEST )
291 return( POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG );
292
293 if( add_len > CTR_DRBG_MAX_INPUT )
294 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
295
296 memset( add_input, 0, CTR_DRBG_SEEDLEN );
297
298 if( ctx->reseed_counter > ctx->reseed_interval ||
299 ctx->prediction_resistance )
300 {
301 if( ( ret = ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
302 return( ret );
303
304 add_len = 0;
305 }
306
307 if( add_len > 0 )
308 {
309 block_cipher_df( add_input, additional, add_len );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000310 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000311 }
312
313 while( output_len > 0 )
314 {
315 /*
316 * Increase counter
317 */
Paul Bakker369e14b2012-04-18 14:16:09 +0000318 for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
319 if( ++ctx->counter[i - 1] != 0 )
320 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000321
322 /*
323 * Crypt counter block
324 */
325 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, tmp );
326
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000327 use_len = (output_len > CTR_DRBG_BLOCKSIZE ) ? CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000328 /*
329 * Copy random block to destination
330 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000331 memcpy( p, tmp, use_len );
332 p += use_len;
333 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000334 }
335
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000336 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000337
338 ctx->reseed_counter++;
339
340 return( 0 );
341}
342
343int ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
344{
345 return ctr_drbg_random_with_add( p_rng, output, output_len, NULL, 0 );
346}
347
Paul Bakkerfc754a92011-12-05 13:23:51 +0000348#if defined(POLARSSL_FS_IO)
349int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path )
350{
351 int ret;
352 FILE *f;
353 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
354
355 if( ( f = fopen( path, "wb" ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000356 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000357
358 if( ( ret = ctr_drbg_random( ctx, buf, CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakker88a22642013-09-11 12:14:16 +0200359 {
360 fclose( f );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000361 return( ret );
Paul Bakker88a22642013-09-11 12:14:16 +0200362 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000363
364 if( fwrite( buf, 1, CTR_DRBG_MAX_INPUT, f ) != CTR_DRBG_MAX_INPUT )
365 {
366 fclose( f );
Paul Bakker69e095c2011-12-10 21:55:01 +0000367 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000368 }
369
370 fclose( f );
371 return( 0 );
372}
373
374int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path )
375{
376 FILE *f;
377 size_t n;
378 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
379
380 if( ( f = fopen( path, "rb" ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000381 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000382
383 fseek( f, 0, SEEK_END );
384 n = (size_t) ftell( f );
385 fseek( f, 0, SEEK_SET );
386
387 if( n > CTR_DRBG_MAX_INPUT )
Paul Bakker88a22642013-09-11 12:14:16 +0200388 {
389 fclose( f );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000390 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker88a22642013-09-11 12:14:16 +0200391 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000392
393 if( fread( buf, 1, n, f ) != n )
394 {
395 fclose( f );
Paul Bakker69e095c2011-12-10 21:55:01 +0000396 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000397 }
398
399 ctr_drbg_update( ctx, buf, n );
400
401 fclose( f );
402
403 return( ctr_drbg_write_seed_file( ctx, path ) );
404}
405#endif /* POLARSSL_FS_IO */
406
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000407#if defined(POLARSSL_SELF_TEST)
408
409#include <stdio.h>
410
411unsigned char entropy_source_pr[96] =
412 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
413 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
414 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
415 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
416 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
417 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
418 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
419 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
420 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
421 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
422 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
423 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
424
425unsigned char entropy_source_nopr[64] =
426 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
427 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
428 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
429 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
430 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
431 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
432 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
433 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
434
435unsigned char nonce_pers_pr[16] =
436 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
437 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
438
439unsigned char nonce_pers_nopr[16] =
440 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
441 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
442
443unsigned char result_pr[16] =
444 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
445 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
446
447unsigned char result_nopr[16] =
448 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
449 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
450
Paul Bakker22a0ce02014-07-08 11:16:44 +0200451static size_t test_offset;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000452int ctr_drbg_self_test_entropy( void *data, unsigned char *buf, size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000453{
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000454 unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000455 memcpy( buf, p + test_offset, len );
456 test_offset += 32;
457 return( 0 );
458}
459
460/*
461 * Checkup routine
462 */
463int ctr_drbg_self_test( int verbose )
464{
465 ctr_drbg_context ctx;
466 unsigned char buf[16];
467
468 /*
469 * Based on a NIST CTR_DRBG test vector (PR = True)
470 */
471 if( verbose != 0 )
472 printf( " CTR_DRBG (PR = TRUE) : " );
473
474 test_offset = 0;
Paul Bakkere88186d2012-01-22 20:29:47 +0000475 if( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy, entropy_source_pr, nonce_pers_pr, 16, 32 ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000476 {
477 if( verbose != 0 )
478 printf( "failed\n" );
479
480 return( 1 );
481 }
482 ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON );
483
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000484 if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000485 {
486 if( verbose != 0 )
487 printf( "failed\n" );
488
489 return( 1 );
490 }
491
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000492 if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000493 {
494 if( verbose != 0 )
495 printf( "failed\n" );
496
497 return( 1 );
498 }
499
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000500 if( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000501 {
502 if( verbose != 0 )
503 printf( "failed\n" );
504
505 return( 1 );
506 }
507
508 if( verbose != 0 )
509 printf( "passed\n" );
510
511 /*
512 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
513 */
514 if( verbose != 0 )
515 printf( " CTR_DRBG (PR = FALSE): " );
516
517 test_offset = 0;
Paul Bakkere88186d2012-01-22 20:29:47 +0000518 if( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy, entropy_source_nopr, nonce_pers_nopr, 16, 32 ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000519 {
520 if( verbose != 0 )
521 printf( "failed\n" );
522
523 return( 1 );
524 }
525
526 if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
527 {
528 if( verbose != 0 )
529 printf( "failed\n" );
530
531 return( 1 );
532 }
533
534 if( ctr_drbg_reseed( &ctx, NULL, 0 ) != 0 )
535 {
536 if( verbose != 0 )
537 printf( "failed\n" );
538
539 return( 1 );
540 }
541
542 if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
543 {
544 if( verbose != 0 )
545 printf( "failed\n" );
546
547 return( 1 );
548 }
549
550 if( memcmp( buf, result_nopr, 16 ) != 0 )
551 {
552 if( verbose != 0 )
553 printf( "failed\n" );
554
555 return( 1 );
556 }
557
558 if( verbose != 0 )
559 printf( "passed\n" );
560
561 if( verbose != 0 )
562 printf( "\n" );
563
564 return( 0 );
565}
566#endif
567
568#endif