]> git.zerfleddert.de Git - proxmark3-svn/blame - common/mbedtls/ctr_drbg.c
EVM fixes and additions (RRG repository PRs 78-82 by @merlokk) (#776)
[proxmark3-svn] / common / mbedtls / ctr_drbg.c
CommitLineData
700d8687
OM
1/*
2 * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
3 *
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 * SPDX-License-Identifier: GPL-2.0
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * This file is part of mbed TLS (https://tls.mbed.org)
22 */
23/*
24 * The NIST SP 800-90 DRBGs are described in the following publication.
25 *
26 * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
27 */
28
29#if !defined(MBEDTLS_CONFIG_FILE)
30#include "mbedtls/config.h"
31#else
32#include MBEDTLS_CONFIG_FILE
33#endif
34
35#if defined(MBEDTLS_CTR_DRBG_C)
36
37#include "mbedtls/ctr_drbg.h"
38#include "mbedtls/platform_util.h"
39
40#include <string.h>
41
42#if defined(MBEDTLS_FS_IO)
43#include <stdio.h>
44#endif
45
46#if defined(MBEDTLS_SELF_TEST)
47#if defined(MBEDTLS_PLATFORM_C)
48#include "mbedtls/platform.h"
49#else
50#include <stdio.h>
51#define mbedtls_printf printf
52#endif /* MBEDTLS_PLATFORM_C */
53#endif /* MBEDTLS_SELF_TEST */
54
55/*
56 * CTR_DRBG context initialization
57 */
58void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
59{
60 memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
61
62#if defined(MBEDTLS_THREADING_C)
63 mbedtls_mutex_init( &ctx->mutex );
64#endif
65}
66
67/*
68 * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow
69 * NIST tests to succeed (which require known length fixed entropy)
70 */
71int mbedtls_ctr_drbg_seed_entropy_len(
72 mbedtls_ctr_drbg_context *ctx,
73 int (*f_entropy)(void *, unsigned char *, size_t),
74 void *p_entropy,
75 const unsigned char *custom,
76 size_t len,
77 size_t entropy_len )
78{
79 int ret;
80 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
81
82 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
83
84 mbedtls_aes_init( &ctx->aes_ctx );
85
86 ctx->f_entropy = f_entropy;
87 ctx->p_entropy = p_entropy;
88
89 ctx->entropy_len = entropy_len;
90 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
91
92 /*
93 * Initialize with an empty key
94 */
95 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
96 {
97 return( ret );
98 }
99
100 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
101 {
102 return( ret );
103 }
104 return( 0 );
105}
106
107int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
108 int (*f_entropy)(void *, unsigned char *, size_t),
109 void *p_entropy,
110 const unsigned char *custom,
111 size_t len )
112{
113 return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy, custom, len,
114 MBEDTLS_CTR_DRBG_ENTROPY_LEN ) );
115}
116
117void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
118{
119 if( ctx == NULL )
120 return;
121
122#if defined(MBEDTLS_THREADING_C)
123 mbedtls_mutex_free( &ctx->mutex );
124#endif
125 mbedtls_aes_free( &ctx->aes_ctx );
126 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
127}
128
129void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
130{
131 ctx->prediction_resistance = resistance;
132}
133
134void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len )
135{
136 ctx->entropy_len = len;
137}
138
139void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval )
140{
141 ctx->reseed_interval = interval;
142}
143
144static int block_cipher_df( unsigned char *output,
145 const unsigned char *data, size_t data_len )
146{
147 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
148 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
149 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
150 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
151 unsigned char *p, *iv;
152 mbedtls_aes_context aes_ctx;
153 int ret = 0;
154
155 int i, j;
156 size_t buf_len, use_len;
157
158 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
159 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
160
161 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
162 mbedtls_aes_init( &aes_ctx );
163
164 /*
165 * Construct IV (16 bytes) and S in buffer
166 * IV = Counter (in 32-bits) padded to 16 with zeroes
167 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
168 * data || 0x80
169 * (Total is padded to a multiple of 16-bytes with zeroes)
170 */
171 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
172 *p++ = ( data_len >> 24 ) & 0xff;
173 *p++ = ( data_len >> 16 ) & 0xff;
174 *p++ = ( data_len >> 8 ) & 0xff;
175 *p++ = ( data_len ) & 0xff;
176 p += 3;
177 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
178 memcpy( p, data, data_len );
179 p[data_len] = 0x80;
180
181 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
182
183 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
184 key[i] = i;
185
186 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
187 {
188 goto exit;
189 }
190
191 /*
192 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
193 */
194 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
195 {
196 p = buf;
197 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
198 use_len = buf_len;
199
200 while( use_len > 0 )
201 {
202 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
203 chain[i] ^= p[i];
204 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
205 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
206 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
207
208 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ) ) != 0 )
209 {
210 goto exit;
211 }
212 }
213
214 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
215
216 /*
217 * Update IV
218 */
219 buf[3]++;
220 }
221
222 /*
223 * Do final encryption with reduced data
224 */
225 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
226 {
227 goto exit;
228 }
229 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
230 p = output;
231
232 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
233 {
234 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) ) != 0 )
235 {
236 goto exit;
237 }
238 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
239 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
240 }
241exit:
242 mbedtls_aes_free( &aes_ctx );
243 /*
244 * tidy up the stack
245 */
246 mbedtls_platform_zeroize( buf, sizeof( buf ) );
247 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
248 mbedtls_platform_zeroize( key, sizeof( key ) );
249 mbedtls_platform_zeroize( chain, sizeof( chain ) );
250 if( 0 != ret )
251 {
252 /*
253 * wipe partial seed from memory
254 */
255 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
256 }
257
258 return( ret );
259}
260
261static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
262 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
263{
264 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
265 unsigned char *p = tmp;
266 int i, j;
267 int ret = 0;
268
269 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
270
271 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
272 {
273 /*
274 * Increase counter
275 */
276 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
277 if( ++ctx->counter[i - 1] != 0 )
278 break;
279
280 /*
281 * Crypt counter block
282 */
283 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 )
284 {
285 return( ret );
286 }
287
288 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
289 }
290
291 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
292 tmp[i] ^= data[i];
293
294 /*
295 * Update key and counter
296 */
297 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
298 {
299 return( ret );
300 }
301 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
302
303 return( 0 );
304}
305
306void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
307 const unsigned char *additional, size_t add_len )
308{
309 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
310
311 if( add_len > 0 )
312 {
313 /* MAX_INPUT would be more logical here, but we have to match
314 * block_cipher_df()'s limits since we can't propagate errors */
315 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
316 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
317
318 block_cipher_df( add_input, additional, add_len );
319 ctr_drbg_update_internal( ctx, add_input );
320 }
321}
322
323int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
324 const unsigned char *additional, size_t len )
325{
326 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
327 size_t seedlen = 0;
328 int ret;
329
330 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
331 len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
332 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
333
334 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
335
336 /*
337 * Gather entropy_len bytes of entropy to seed state
338 */
339 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
340 ctx->entropy_len ) )
341 {
342 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
343 }
344
345 seedlen += ctx->entropy_len;
346
347 /*
348 * Add additional data
349 */
350 if( additional && len )
351 {
352 memcpy( seed + seedlen, additional, len );
353 seedlen += len;
354 }
355
356 /*
357 * Reduce to 384 bits
358 */
359 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
360 {
361 return( ret );
362 }
363
364 /*
365 * Update state
366 */
367 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
368 {
369 return( ret );
370 }
371 ctx->reseed_counter = 1;
372
373 return( 0 );
374}
375
376int mbedtls_ctr_drbg_random_with_add( void *p_rng,
377 unsigned char *output, size_t output_len,
378 const unsigned char *additional, size_t add_len )
379{
380 int ret = 0;
381 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
382 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
383 unsigned char *p = output;
384 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
385 int i;
386 size_t use_len;
387
388 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
389 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
390
391 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
392 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
393
394 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
395
396 if( ctx->reseed_counter > ctx->reseed_interval ||
397 ctx->prediction_resistance )
398 {
399 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
400 {
401 return( ret );
402 }
403 add_len = 0;
404 }
405
406 if( add_len > 0 )
407 {
408 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
409 {
410 return( ret );
411 }
412 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
413 {
414 return( ret );
415 }
416 }
417
418 while( output_len > 0 )
419 {
420 /*
421 * Increase counter
422 */
423 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
424 if( ++ctx->counter[i - 1] != 0 )
425 break;
426
427 /*
428 * Crypt counter block
429 */
430 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 )
431 {
432 return( ret );
433 }
434
435 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
436 output_len;
437 /*
438 * Copy random block to destination
439 */
440 memcpy( p, tmp, use_len );
441 p += use_len;
442 output_len -= use_len;
443 }
444
445 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
446 {
447 return( ret );
448 }
449
450 ctx->reseed_counter++;
451
452 return( 0 );
453}
454
455int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
456{
457 int ret;
458 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
459
460#if defined(MBEDTLS_THREADING_C)
461 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
462 return( ret );
463#endif
464
465 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
466
467#if defined(MBEDTLS_THREADING_C)
468 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
469 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
470#endif
471
472 return( ret );
473}
474
475#if defined(MBEDTLS_FS_IO)
476int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
477{
478 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
479 FILE *f;
480 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
481
482 if( ( f = fopen( path, "wb" ) ) == NULL )
483 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
484
485 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
486 goto exit;
487
488 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
489 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
490 else
491 ret = 0;
492
493exit:
494 mbedtls_platform_zeroize( buf, sizeof( buf ) );
495
496 fclose( f );
497 return( ret );
498}
499
500int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
501{
502 int ret = 0;
503 FILE *f;
504 size_t n;
505 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
506
507 if( ( f = fopen( path, "rb" ) ) == NULL )
508 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
509
510 fseek( f, 0, SEEK_END );
511 n = (size_t) ftell( f );
512 fseek( f, 0, SEEK_SET );
513
514 if( n > MBEDTLS_CTR_DRBG_MAX_INPUT )
515 {
516 fclose( f );
517 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
518 }
519
520 if( fread( buf, 1, n, f ) != n )
521 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
522 else
523 mbedtls_ctr_drbg_update( ctx, buf, n );
524
525 fclose( f );
526
527 mbedtls_platform_zeroize( buf, sizeof( buf ) );
528
529 if( ret != 0 )
530 return( ret );
531
532 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
533}
534#endif /* MBEDTLS_FS_IO */
535
536#if defined(MBEDTLS_SELF_TEST)
537
538static const unsigned char entropy_source_pr[96] =
539 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
540 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
541 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
542 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
543 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
544 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
545 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
546 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
547 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
548 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
549 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
550 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
551
552static const unsigned char entropy_source_nopr[64] =
553 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
554 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
555 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
556 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
557 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
558 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
559 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
560 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
561
562static const unsigned char nonce_pers_pr[16] =
563 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
564 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
565
566static const unsigned char nonce_pers_nopr[16] =
567 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
568 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
569
570static const unsigned char result_pr[16] =
571 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
572 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
573
574static const unsigned char result_nopr[16] =
575 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
576 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
577
578static size_t test_offset;
579static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
580 size_t len )
581{
582 const unsigned char *p = data;
583 memcpy( buf, p + test_offset, len );
584 test_offset += len;
585 return( 0 );
586}
587
588#define CHK( c ) if( (c) != 0 ) \
589 { \
590 if( verbose != 0 ) \
591 mbedtls_printf( "failed\n" ); \
592 return( 1 ); \
593 }
594
595/*
596 * Checkup routine
597 */
598int mbedtls_ctr_drbg_self_test( int verbose )
599{
600 mbedtls_ctr_drbg_context ctx;
601 unsigned char buf[16];
602
603 mbedtls_ctr_drbg_init( &ctx );
604
605 /*
606 * Based on a NIST CTR_DRBG test vector (PR = True)
607 */
608 if( verbose != 0 )
609 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
610
611 test_offset = 0;
612 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
613 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
614 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
615 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
616 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
617 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
618
619 mbedtls_ctr_drbg_free( &ctx );
620
621 if( verbose != 0 )
622 mbedtls_printf( "passed\n" );
623
624 /*
625 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
626 */
627 if( verbose != 0 )
628 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
629
630 mbedtls_ctr_drbg_init( &ctx );
631
632 test_offset = 0;
633 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
634 (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
635 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
636 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
637 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
638 CHK( memcmp( buf, result_nopr, 16 ) );
639
640 mbedtls_ctr_drbg_free( &ctx );
641
642 if( verbose != 0 )
643 mbedtls_printf( "passed\n" );
644
645 if( verbose != 0 )
646 mbedtls_printf( "\n" );
647
648 return( 0 );
649}
650#endif /* MBEDTLS_SELF_TEST */
651
652#endif /* MBEDTLS_CTR_DRBG_C */
Impressum, Datenschutz