source: azure_iot_hub_mbedtls/trunk/mbedtls-2.16.1/library/ctr_drbg.c@ 398

Last change on this file since 398 was 398, checked in by coas-nagasima, 5 years ago

mbedTLS版Azure IoT Hub接続サンプルのソースコードを追加

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