Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
ctr_drbg.c
00001 /* 00002 * CTR_DRBG implementation based on AES-256 (NIST SP 800-90) 00003 * 00004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 00005 * SPDX-License-Identifier: Apache-2.0 00006 * 00007 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00008 * not use this file except in compliance with the License. 00009 * You may obtain a copy of the License at 00010 * 00011 * http://www.apache.org/licenses/LICENSE-2.0 00012 * 00013 * Unless required by applicable law or agreed to in writing, software 00014 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00015 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00016 * See the License for the specific language governing permissions and 00017 * limitations under the License. 00018 * 00019 * This file is part of mbed TLS (https://tls.mbed.org) 00020 */ 00021 /* 00022 * The NIST SP 800-90 DRBGs are described in the following publication. 00023 * 00024 * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf 00025 */ 00026 00027 #if !defined(MBEDTLS_CONFIG_FILE) 00028 #include "mbedtls/config.h" 00029 #else 00030 #include MBEDTLS_CONFIG_FILE 00031 #endif 00032 00033 #if defined(MBEDTLS_CTR_DRBG_C) 00034 00035 #include "mbedtls/ctr_drbg.h" 00036 #include "mbedtls/platform_util.h" 00037 00038 #include <string.h> 00039 00040 #if defined(MBEDTLS_FS_IO) 00041 #include <stdio.h> 00042 #endif 00043 00044 #if defined(MBEDTLS_SELF_TEST) 00045 #if defined(MBEDTLS_PLATFORM_C) 00046 #include "mbedtls/platform.h" 00047 #else 00048 #include <stdio.h> 00049 #define mbedtls_printf printf 00050 #endif /* MBEDTLS_PLATFORM_C */ 00051 #endif /* MBEDTLS_SELF_TEST */ 00052 00053 /* 00054 * CTR_DRBG context initialization 00055 */ 00056 void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ) 00057 { 00058 memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) ); 00059 00060 #if defined(MBEDTLS_THREADING_C) 00061 mbedtls_mutex_init( &ctx->mutex ); 00062 #endif 00063 } 00064 00065 /* 00066 * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow 00067 * NIST tests to succeed (which require known length fixed entropy) 00068 */ 00069 /* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) 00070 * mbedtls_ctr_drbg_seed_entropy_len(ctx, f_entropy, p_entropy, 00071 * custom, len, entropy_len) 00072 * implements 00073 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, 00074 * security_strength) -> initial_working_state 00075 * with inputs 00076 * custom[:len] = nonce || personalization_string 00077 * where entropy_input comes from f_entropy for entropy_len bytes 00078 * and with outputs 00079 * ctx = initial_working_state 00080 */ 00081 int mbedtls_ctr_drbg_seed_entropy_len( 00082 mbedtls_ctr_drbg_context *ctx, 00083 int (*f_entropy)(void *, unsigned char *, size_t), 00084 void *p_entropy, 00085 const unsigned char *custom, 00086 size_t len, 00087 size_t entropy_len ) 00088 { 00089 int ret; 00090 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; 00091 00092 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE ); 00093 00094 mbedtls_aes_init( &ctx->aes_ctx ); 00095 00096 ctx->f_entropy = f_entropy; 00097 ctx->p_entropy = p_entropy; 00098 00099 ctx->entropy_len = entropy_len; 00100 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; 00101 00102 /* 00103 * Initialize with an empty key 00104 */ 00105 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx , key, 00106 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) 00107 { 00108 return( ret ); 00109 } 00110 00111 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 ) 00112 { 00113 return( ret ); 00114 } 00115 return( 0 ); 00116 } 00117 00118 int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, 00119 int (*f_entropy)(void *, unsigned char *, size_t), 00120 void *p_entropy, 00121 const unsigned char *custom, 00122 size_t len ) 00123 { 00124 return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy, 00125 custom, len, 00126 MBEDTLS_CTR_DRBG_ENTROPY_LEN ) ); 00127 } 00128 00129 void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ) 00130 { 00131 if( ctx == NULL ) 00132 return; 00133 00134 #if defined(MBEDTLS_THREADING_C) 00135 mbedtls_mutex_free( &ctx->mutex ); 00136 #endif 00137 mbedtls_aes_free( &ctx->aes_ctx ); 00138 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) ); 00139 } 00140 00141 void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, 00142 int resistance ) 00143 { 00144 ctx->prediction_resistance = resistance; 00145 } 00146 00147 void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, 00148 size_t len ) 00149 { 00150 ctx->entropy_len = len; 00151 } 00152 00153 void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, 00154 int interval ) 00155 { 00156 ctx->reseed_interval = interval; 00157 } 00158 00159 static int block_cipher_df( unsigned char *output, 00160 const unsigned char *data, size_t data_len ) 00161 { 00162 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + 00163 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16]; 00164 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; 00165 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; 00166 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE]; 00167 unsigned char *p, *iv; 00168 mbedtls_aes_context aes_ctx; 00169 int ret = 0; 00170 00171 int i, j; 00172 size_t buf_len, use_len; 00173 00174 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) 00175 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); 00176 00177 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + 00178 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 ); 00179 mbedtls_aes_init( &aes_ctx ); 00180 00181 /* 00182 * Construct IV (16 bytes) and S in buffer 00183 * IV = Counter (in 32-bits) padded to 16 with zeroes 00184 * S = Length input string (in 32-bits) || Length of output (in 32-bits) || 00185 * data || 0x80 00186 * (Total is padded to a multiple of 16-bytes with zeroes) 00187 */ 00188 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE; 00189 *p++ = ( data_len >> 24 ) & 0xff; 00190 *p++ = ( data_len >> 16 ) & 0xff; 00191 *p++ = ( data_len >> 8 ) & 0xff; 00192 *p++ = ( data_len ) & 0xff; 00193 p += 3; 00194 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN; 00195 memcpy( p, data, data_len ); 00196 p[data_len] = 0x80; 00197 00198 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1; 00199 00200 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ ) 00201 key[i] = i; 00202 00203 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, 00204 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) 00205 { 00206 goto exit; 00207 } 00208 00209 /* 00210 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data 00211 */ 00212 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) 00213 { 00214 p = buf; 00215 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE ); 00216 use_len = buf_len; 00217 00218 while( use_len > 0 ) 00219 { 00220 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ ) 00221 chain[i] ^= p[i]; 00222 p += MBEDTLS_CTR_DRBG_BLOCKSIZE; 00223 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? 00224 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len; 00225 00226 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, 00227 chain, chain ) ) != 0 ) 00228 { 00229 goto exit; 00230 } 00231 } 00232 00233 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE ); 00234 00235 /* 00236 * Update IV 00237 */ 00238 buf[3]++; 00239 } 00240 00241 /* 00242 * Do final encryption with reduced data 00243 */ 00244 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, 00245 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) 00246 { 00247 goto exit; 00248 } 00249 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE; 00250 p = output; 00251 00252 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) 00253 { 00254 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, 00255 iv, iv ) ) != 0 ) 00256 { 00257 goto exit; 00258 } 00259 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE ); 00260 p += MBEDTLS_CTR_DRBG_BLOCKSIZE; 00261 } 00262 exit: 00263 mbedtls_aes_free( &aes_ctx ); 00264 /* 00265 * tidy up the stack 00266 */ 00267 mbedtls_platform_zeroize( buf, sizeof( buf ) ); 00268 mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); 00269 mbedtls_platform_zeroize( key, sizeof( key ) ); 00270 mbedtls_platform_zeroize( chain, sizeof( chain ) ); 00271 if( 0 != ret ) 00272 { 00273 /* 00274 * wipe partial seed from memory 00275 */ 00276 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN ); 00277 } 00278 00279 return( ret ); 00280 } 00281 00282 /* CTR_DRBG_Update (SP 800-90A §10.2.1.2) 00283 * ctr_drbg_update_internal(ctx, provided_data) 00284 * implements 00285 * CTR_DRBG_Update(provided_data, Key, V) 00286 * with inputs and outputs 00287 * ctx->aes_ctx = Key 00288 * ctx->counter = V 00289 */ 00290 static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx, 00291 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] ) 00292 { 00293 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; 00294 unsigned char *p = tmp; 00295 int i, j; 00296 int ret = 0; 00297 00298 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN ); 00299 00300 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) 00301 { 00302 /* 00303 * Increase counter 00304 */ 00305 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- ) 00306 if( ++ctx->counter [i - 1] != 0 ) 00307 break; 00308 00309 /* 00310 * Crypt counter block 00311 */ 00312 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx , MBEDTLS_AES_ENCRYPT, 00313 ctx->counter , p ) ) != 0 ) 00314 { 00315 goto exit; 00316 } 00317 00318 p += MBEDTLS_CTR_DRBG_BLOCKSIZE; 00319 } 00320 00321 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ ) 00322 tmp[i] ^= data[i]; 00323 00324 /* 00325 * Update key and counter 00326 */ 00327 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx , tmp, 00328 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) 00329 { 00330 goto exit; 00331 } 00332 memcpy( ctx->counter , tmp + MBEDTLS_CTR_DRBG_KEYSIZE, 00333 MBEDTLS_CTR_DRBG_BLOCKSIZE ); 00334 00335 exit: 00336 mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); 00337 return( ret ); 00338 } 00339 00340 /* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) 00341 * mbedtls_ctr_drbg_update(ctx, additional, add_len) 00342 * implements 00343 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, 00344 * security_strength) -> initial_working_state 00345 * with inputs 00346 * ctx->counter = all-bits-0 00347 * ctx->aes_ctx = context from all-bits-0 key 00348 * additional[:add_len] = entropy_input || nonce || personalization_string 00349 * and with outputs 00350 * ctx = initial_working_state 00351 */ 00352 int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx, 00353 const unsigned char *additional, 00354 size_t add_len ) 00355 { 00356 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; 00357 int ret; 00358 00359 if( add_len == 0 ) 00360 return( 0 ); 00361 00362 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 ) 00363 goto exit; 00364 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) 00365 goto exit; 00366 00367 exit: 00368 mbedtls_platform_zeroize( add_input, sizeof( add_input ) ); 00369 return( ret ); 00370 } 00371 00372 #if !defined(MBEDTLS_DEPRECATED_REMOVED) 00373 void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, 00374 const unsigned char *additional, 00375 size_t add_len ) 00376 { 00377 /* MAX_INPUT would be more logical here, but we have to match 00378 * block_cipher_df()'s limits since we can't propagate errors */ 00379 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) 00380 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT; 00381 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len ); 00382 } 00383 #endif /* MBEDTLS_DEPRECATED_REMOVED */ 00384 00385 /* CTR_DRBG_Reseed with derivation function (SP 800-90A §10.2.1.4.2) 00386 * mbedtls_ctr_drbg_reseed(ctx, additional, len) 00387 * implements 00388 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input) 00389 * -> new_working_state 00390 * with inputs 00391 * ctx contains working_state 00392 * additional[:len] = additional_input 00393 * and entropy_input comes from calling ctx->f_entropy 00394 * and with output 00395 * ctx contains new_working_state 00396 */ 00397 int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, 00398 const unsigned char *additional, size_t len ) 00399 { 00400 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT]; 00401 size_t seedlen = 0; 00402 int ret; 00403 00404 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT || 00405 len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len ) 00406 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); 00407 00408 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ); 00409 00410 /* 00411 * Gather entropy_len bytes of entropy to seed state 00412 */ 00413 if( 0 != ctx->f_entropy ( ctx->p_entropy , seed, 00414 ctx->entropy_len ) ) 00415 { 00416 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED ); 00417 } 00418 00419 seedlen += ctx->entropy_len ; 00420 00421 /* 00422 * Add additional data 00423 */ 00424 if( additional && len ) 00425 { 00426 memcpy( seed + seedlen, additional, len ); 00427 seedlen += len; 00428 } 00429 00430 /* 00431 * Reduce to 384 bits 00432 */ 00433 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 ) 00434 goto exit; 00435 00436 /* 00437 * Update state 00438 */ 00439 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 ) 00440 goto exit; 00441 ctx->reseed_counter = 1; 00442 00443 exit: 00444 mbedtls_platform_zeroize( seed, sizeof( seed ) ); 00445 return( ret ); 00446 } 00447 00448 /* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2) 00449 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len) 00450 * implements 00451 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len]) 00452 * -> working_state_after_reseed 00453 * if required, then 00454 * CTR_DRBG_Generate(working_state_after_reseed, 00455 * requested_number_of_bits, additional_input) 00456 * -> status, returned_bits, new_working_state 00457 * with inputs 00458 * ctx contains working_state 00459 * requested_number_of_bits = 8 * output_len 00460 * additional[:add_len] = additional_input 00461 * and entropy_input comes from calling ctx->f_entropy 00462 * and with outputs 00463 * status = SUCCESS (this function does the reseed internally) 00464 * returned_bits = output[:output_len] 00465 * ctx contains new_working_state 00466 */ 00467 int mbedtls_ctr_drbg_random_with_add( void *p_rng, 00468 unsigned char *output, size_t output_len, 00469 const unsigned char *additional, size_t add_len ) 00470 { 00471 int ret = 0; 00472 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; 00473 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; 00474 unsigned char *p = output; 00475 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE]; 00476 int i; 00477 size_t use_len; 00478 00479 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST ) 00480 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG ); 00481 00482 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT ) 00483 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); 00484 00485 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN ); 00486 00487 if( ctx->reseed_counter > ctx->reseed_interval || 00488 ctx->prediction_resistance ) 00489 { 00490 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 ) 00491 { 00492 return( ret ); 00493 } 00494 add_len = 0; 00495 } 00496 00497 if( add_len > 0 ) 00498 { 00499 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 ) 00500 goto exit; 00501 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) 00502 goto exit; 00503 } 00504 00505 while( output_len > 0 ) 00506 { 00507 /* 00508 * Increase counter 00509 */ 00510 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- ) 00511 if( ++ctx->counter [i - 1] != 0 ) 00512 break; 00513 00514 /* 00515 * Crypt counter block 00516 */ 00517 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx , MBEDTLS_AES_ENCRYPT, 00518 ctx->counter , tmp ) ) != 0 ) 00519 { 00520 goto exit; 00521 } 00522 00523 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) 00524 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len; 00525 /* 00526 * Copy random block to destination 00527 */ 00528 memcpy( p, tmp, use_len ); 00529 p += use_len; 00530 output_len -= use_len; 00531 } 00532 00533 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) 00534 goto exit; 00535 00536 ctx->reseed_counter ++; 00537 00538 exit: 00539 mbedtls_platform_zeroize( add_input, sizeof( add_input ) ); 00540 mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); 00541 return( 0 ); 00542 } 00543 00544 int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, 00545 size_t output_len ) 00546 { 00547 int ret; 00548 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; 00549 00550 #if defined(MBEDTLS_THREADING_C) 00551 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) 00552 return( ret ); 00553 #endif 00554 00555 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 ); 00556 00557 #if defined(MBEDTLS_THREADING_C) 00558 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) 00559 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); 00560 #endif 00561 00562 return( ret ); 00563 } 00564 00565 #if defined(MBEDTLS_FS_IO) 00566 int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, 00567 const char *path ) 00568 { 00569 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; 00570 FILE *f; 00571 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; 00572 00573 if( ( f = fopen( path, "wb" ) ) == NULL ) 00574 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); 00575 00576 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, 00577 MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 ) 00578 goto exit; 00579 00580 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != 00581 MBEDTLS_CTR_DRBG_MAX_INPUT ) 00582 { 00583 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; 00584 } 00585 else 00586 { 00587 ret = 0; 00588 } 00589 00590 exit: 00591 mbedtls_platform_zeroize( buf, sizeof( buf ) ); 00592 00593 fclose( f ); 00594 return( ret ); 00595 } 00596 00597 int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, 00598 const char *path ) 00599 { 00600 int ret = 0; 00601 FILE *f = NULL; 00602 size_t n; 00603 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; 00604 unsigned char c; 00605 00606 if( ( f = fopen( path, "rb" ) ) == NULL ) 00607 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); 00608 00609 n = fread( buf, 1, sizeof( buf ), f ); 00610 if( fread( &c, 1, 1, f ) != 0 ) 00611 { 00612 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; 00613 goto exit; 00614 } 00615 if( n == 0 || ferror( f ) ) 00616 { 00617 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; 00618 goto exit; 00619 } 00620 fclose( f ); 00621 f = NULL; 00622 00623 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n ); 00624 00625 exit: 00626 mbedtls_platform_zeroize( buf, sizeof( buf ) ); 00627 if( f != NULL ) 00628 fclose( f ); 00629 if( ret != 0 ) 00630 return( ret ); 00631 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) ); 00632 } 00633 #endif /* MBEDTLS_FS_IO */ 00634 00635 #if defined(MBEDTLS_SELF_TEST) 00636 00637 static const unsigned char entropy_source_pr[96] = 00638 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16, 00639 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02, 00640 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b, 00641 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb, 00642 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9, 00643 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95, 00644 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63, 00645 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3, 00646 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31, 00647 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4, 00648 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56, 00649 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 }; 00650 00651 static const unsigned char entropy_source_nopr[64] = 00652 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14, 00653 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe, 00654 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d, 00655 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20, 00656 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9, 00657 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46, 00658 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e, 00659 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e }; 00660 00661 static const unsigned char nonce_pers_pr[16] = 00662 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2, 00663 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c }; 00664 00665 static const unsigned char nonce_pers_nopr[16] = 00666 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5, 00667 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f }; 00668 00669 static const unsigned char result_pr[16] = 00670 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f, 00671 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 }; 00672 00673 static const unsigned char result_nopr[16] = 00674 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88, 00675 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f }; 00676 00677 static size_t test_offset; 00678 static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf, 00679 size_t len ) 00680 { 00681 const unsigned char *p = data; 00682 memcpy( buf, p + test_offset, len ); 00683 test_offset += len; 00684 return( 0 ); 00685 } 00686 00687 #define CHK( c ) if( (c) != 0 ) \ 00688 { \ 00689 if( verbose != 0 ) \ 00690 mbedtls_printf( "failed\n" ); \ 00691 return( 1 ); \ 00692 } 00693 00694 /* 00695 * Checkup routine 00696 */ 00697 int mbedtls_ctr_drbg_self_test( int verbose ) 00698 { 00699 mbedtls_ctr_drbg_context ctx; 00700 unsigned char buf[16]; 00701 00702 mbedtls_ctr_drbg_init( &ctx ); 00703 00704 /* 00705 * Based on a NIST CTR_DRBG test vector (PR = True) 00706 */ 00707 if( verbose != 0 ) 00708 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " ); 00709 00710 test_offset = 0; 00711 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy, 00712 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) ); 00713 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON ); 00714 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); 00715 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); 00716 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); 00717 00718 mbedtls_ctr_drbg_free( &ctx ); 00719 00720 if( verbose != 0 ) 00721 mbedtls_printf( "passed\n" ); 00722 00723 /* 00724 * Based on a NIST CTR_DRBG test vector (PR = FALSE) 00725 */ 00726 if( verbose != 0 ) 00727 mbedtls_printf( " CTR_DRBG (PR = FALSE): " ); 00728 00729 mbedtls_ctr_drbg_init( &ctx ); 00730 00731 test_offset = 0; 00732 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy, 00733 (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) ); 00734 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) ); 00735 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) ); 00736 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) ); 00737 CHK( memcmp( buf, result_nopr, 16 ) ); 00738 00739 mbedtls_ctr_drbg_free( &ctx ); 00740 00741 if( verbose != 0 ) 00742 mbedtls_printf( "passed\n" ); 00743 00744 if( verbose != 0 ) 00745 mbedtls_printf( "\n" ); 00746 00747 return( 0 ); 00748 } 00749 #endif /* MBEDTLS_SELF_TEST */ 00750 00751 #endif /* MBEDTLS_CTR_DRBG_C */
Generated on Tue Jul 12 2022 13:54:16 by
1.7.2