mbed TLS Build
Dependents: Encypting_Funcional
hmac_drbg.c
00001 /* 00002 * HMAC_DRBG implementation (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 /* 00023 * The NIST SP 800-90A DRBGs are described in the following publication. 00024 * http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf 00025 * References below are based on rev. 1 (January 2012). 00026 */ 00027 00028 #if !defined(MBEDTLS_CONFIG_FILE) 00029 #include "mbedtls/config.h" 00030 #else 00031 #include MBEDTLS_CONFIG_FILE 00032 #endif 00033 00034 #if defined(MBEDTLS_HMAC_DRBG_C) 00035 00036 #include "mbedtls/hmac_drbg.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_SELF_TEST */ 00051 #endif /* MBEDTLS_PLATFORM_C */ 00052 00053 /* Implementation that should never be optimized out by the compiler */ 00054 static void mbedtls_zeroize( void *v, size_t n ) { 00055 volatile unsigned char *p = v; while( n-- ) *p++ = 0; 00056 } 00057 00058 /* 00059 * HMAC_DRBG context initialization 00060 */ 00061 void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ) 00062 { 00063 memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) ); 00064 00065 #if defined(MBEDTLS_THREADING_C) 00066 mbedtls_mutex_init( &ctx->mutex ); 00067 #endif 00068 } 00069 00070 /* 00071 * HMAC_DRBG update, using optional additional data (10.1.2.2) 00072 */ 00073 void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, 00074 const unsigned char *additional, size_t add_len ) 00075 { 00076 size_t md_len = mbedtls_md_get_size( ctx->md_ctx .md_info ); 00077 unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1; 00078 unsigned char sep[1]; 00079 unsigned char K[MBEDTLS_MD_MAX_SIZE]; 00080 00081 for( sep[0] = 0; sep[0] < rounds; sep[0]++ ) 00082 { 00083 /* Step 1 or 4 */ 00084 mbedtls_md_hmac_reset( &ctx->md_ctx ); 00085 mbedtls_md_hmac_update( &ctx->md_ctx , ctx->V , md_len ); 00086 mbedtls_md_hmac_update( &ctx->md_ctx , sep, 1 ); 00087 if( rounds == 2 ) 00088 mbedtls_md_hmac_update( &ctx->md_ctx , additional, add_len ); 00089 mbedtls_md_hmac_finish( &ctx->md_ctx , K ); 00090 00091 /* Step 2 or 5 */ 00092 mbedtls_md_hmac_starts( &ctx->md_ctx , K, md_len ); 00093 mbedtls_md_hmac_update( &ctx->md_ctx , ctx->V , md_len ); 00094 mbedtls_md_hmac_finish( &ctx->md_ctx , ctx->V ); 00095 } 00096 } 00097 00098 /* 00099 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA) 00100 */ 00101 int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx, 00102 const mbedtls_md_info_t * md_info, 00103 const unsigned char *data, size_t data_len ) 00104 { 00105 int ret; 00106 00107 if( ( ret = mbedtls_md_setup( &ctx->md_ctx , md_info, 1 ) ) != 0 ) 00108 return( ret ); 00109 00110 /* 00111 * Set initial working state. 00112 * Use the V memory location, which is currently all 0, to initialize the 00113 * MD context with an all-zero key. Then set V to its initial value. 00114 */ 00115 mbedtls_md_hmac_starts( &ctx->md_ctx , ctx->V , mbedtls_md_get_size( md_info ) ); 00116 memset( ctx->V , 0x01, mbedtls_md_get_size( md_info ) ); 00117 00118 mbedtls_hmac_drbg_update( ctx, data, data_len ); 00119 00120 return( 0 ); 00121 } 00122 00123 /* 00124 * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman) 00125 */ 00126 int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, 00127 const unsigned char *additional, size_t len ) 00128 { 00129 unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT]; 00130 size_t seedlen; 00131 00132 /* III. Check input length */ 00133 if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT || 00134 ctx->entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT ) 00135 { 00136 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); 00137 } 00138 00139 memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT ); 00140 00141 /* IV. Gather entropy_len bytes of entropy for the seed */ 00142 if( ctx->f_entropy ( ctx->p_entropy , seed, ctx->entropy_len ) != 0 ) 00143 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED ); 00144 00145 seedlen = ctx->entropy_len ; 00146 00147 /* 1. Concatenate entropy and additional data if any */ 00148 if( additional != NULL && len != 0 ) 00149 { 00150 memcpy( seed + seedlen, additional, len ); 00151 seedlen += len; 00152 } 00153 00154 /* 2. Update state */ 00155 mbedtls_hmac_drbg_update( ctx, seed, seedlen ); 00156 00157 /* 3. Reset reseed_counter */ 00158 ctx->reseed_counter = 1; 00159 00160 /* 4. Done */ 00161 return( 0 ); 00162 } 00163 00164 /* 00165 * HMAC_DRBG initialisation (10.1.2.3 + 9.1) 00166 */ 00167 int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, 00168 const mbedtls_md_info_t * md_info, 00169 int (*f_entropy)(void *, unsigned char *, size_t), 00170 void *p_entropy, 00171 const unsigned char *custom, 00172 size_t len ) 00173 { 00174 int ret; 00175 size_t entropy_len, md_size; 00176 00177 if( ( ret = mbedtls_md_setup( &ctx->md_ctx , md_info, 1 ) ) != 0 ) 00178 return( ret ); 00179 00180 md_size = mbedtls_md_get_size( md_info ); 00181 00182 /* 00183 * Set initial working state. 00184 * Use the V memory location, which is currently all 0, to initialize the 00185 * MD context with an all-zero key. Then set V to its initial value. 00186 */ 00187 mbedtls_md_hmac_starts( &ctx->md_ctx , ctx->V , md_size ); 00188 memset( ctx->V , 0x01, md_size ); 00189 00190 ctx->f_entropy = f_entropy; 00191 ctx->p_entropy = p_entropy; 00192 00193 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL; 00194 00195 /* 00196 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by 00197 * each hash function, then according to SP800-90A rev1 10.1 table 2, 00198 * min_entropy_len (in bits) is security_strength. 00199 * 00200 * (This also matches the sizes used in the NIST test vectors.) 00201 */ 00202 entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */ 00203 md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */ 00204 32; /* better (256+) -> 256 bits */ 00205 00206 /* 00207 * For initialisation, use more entropy to emulate a nonce 00208 * (Again, matches test vectors.) 00209 */ 00210 ctx->entropy_len = entropy_len * 3 / 2; 00211 00212 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, custom, len ) ) != 0 ) 00213 return( ret ); 00214 00215 ctx->entropy_len = entropy_len; 00216 00217 return( 0 ); 00218 } 00219 00220 /* 00221 * Set prediction resistance 00222 */ 00223 void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx, 00224 int resistance ) 00225 { 00226 ctx->prediction_resistance = resistance; 00227 } 00228 00229 /* 00230 * Set entropy length grabbed for reseeds 00231 */ 00232 void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len ) 00233 { 00234 ctx->entropy_len = len; 00235 } 00236 00237 /* 00238 * Set reseed interval 00239 */ 00240 void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval ) 00241 { 00242 ctx->reseed_interval = interval; 00243 } 00244 00245 /* 00246 * HMAC_DRBG random function with optional additional data: 00247 * 10.1.2.5 (arabic) + 9.3 (Roman) 00248 */ 00249 int mbedtls_hmac_drbg_random_with_add( void *p_rng, 00250 unsigned char *output, size_t out_len, 00251 const unsigned char *additional, size_t add_len ) 00252 { 00253 int ret; 00254 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng; 00255 size_t md_len = mbedtls_md_get_size( ctx->md_ctx .md_info ); 00256 size_t left = out_len; 00257 unsigned char *out = output; 00258 00259 /* II. Check request length */ 00260 if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST ) 00261 return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG ); 00262 00263 /* III. Check input length */ 00264 if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT ) 00265 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); 00266 00267 /* 1. (aka VII and IX) Check reseed counter and PR */ 00268 if( ctx->f_entropy != NULL && /* For no-reseeding instances */ 00269 ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON || 00270 ctx->reseed_counter > ctx->reseed_interval ) ) 00271 { 00272 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 ) 00273 return( ret ); 00274 00275 add_len = 0; /* VII.4 */ 00276 } 00277 00278 /* 2. Use additional data if any */ 00279 if( additional != NULL && add_len != 0 ) 00280 mbedtls_hmac_drbg_update( ctx, additional, add_len ); 00281 00282 /* 3, 4, 5. Generate bytes */ 00283 while( left != 0 ) 00284 { 00285 size_t use_len = left > md_len ? md_len : left; 00286 00287 mbedtls_md_hmac_reset( &ctx->md_ctx ); 00288 mbedtls_md_hmac_update( &ctx->md_ctx , ctx->V , md_len ); 00289 mbedtls_md_hmac_finish( &ctx->md_ctx , ctx->V ); 00290 00291 memcpy( out, ctx->V , use_len ); 00292 out += use_len; 00293 left -= use_len; 00294 } 00295 00296 /* 6. Update */ 00297 mbedtls_hmac_drbg_update( ctx, additional, add_len ); 00298 00299 /* 7. Update reseed counter */ 00300 ctx->reseed_counter ++; 00301 00302 /* 8. Done */ 00303 return( 0 ); 00304 } 00305 00306 /* 00307 * HMAC_DRBG random function 00308 */ 00309 int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len ) 00310 { 00311 int ret; 00312 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng; 00313 00314 #if defined(MBEDTLS_THREADING_C) 00315 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) 00316 return( ret ); 00317 #endif 00318 00319 ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 ); 00320 00321 #if defined(MBEDTLS_THREADING_C) 00322 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) 00323 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); 00324 #endif 00325 00326 return( ret ); 00327 } 00328 00329 /* 00330 * Free an HMAC_DRBG context 00331 */ 00332 void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ) 00333 { 00334 if( ctx == NULL ) 00335 return; 00336 00337 #if defined(MBEDTLS_THREADING_C) 00338 mbedtls_mutex_free( &ctx->mutex ); 00339 #endif 00340 mbedtls_md_free( &ctx->md_ctx ); 00341 mbedtls_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) ); 00342 } 00343 00344 #if defined(MBEDTLS_FS_IO) 00345 int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ) 00346 { 00347 int ret; 00348 FILE *f; 00349 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ]; 00350 00351 if( ( f = fopen( path, "wb" ) ) == NULL ) 00352 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); 00353 00354 if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 ) 00355 goto exit; 00356 00357 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) ) 00358 { 00359 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; 00360 goto exit; 00361 } 00362 00363 ret = 0; 00364 00365 exit: 00366 fclose( f ); 00367 return( ret ); 00368 } 00369 00370 int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ) 00371 { 00372 FILE *f; 00373 size_t n; 00374 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ]; 00375 00376 if( ( f = fopen( path, "rb" ) ) == NULL ) 00377 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); 00378 00379 fseek( f, 0, SEEK_END ); 00380 n = (size_t) ftell( f ); 00381 fseek( f, 0, SEEK_SET ); 00382 00383 if( n > MBEDTLS_HMAC_DRBG_MAX_INPUT ) 00384 { 00385 fclose( f ); 00386 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); 00387 } 00388 00389 if( fread( buf, 1, n, f ) != n ) 00390 { 00391 fclose( f ); 00392 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); 00393 } 00394 00395 fclose( f ); 00396 00397 mbedtls_hmac_drbg_update( ctx, buf, n ); 00398 00399 return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) ); 00400 } 00401 #endif /* MBEDTLS_FS_IO */ 00402 00403 00404 #if defined(MBEDTLS_SELF_TEST) 00405 00406 #if !defined(MBEDTLS_SHA1_C) 00407 /* Dummy checkup routine */ 00408 int mbedtls_hmac_drbg_self_test( int verbose ) 00409 { 00410 (void) verbose; 00411 return( 0 ); 00412 } 00413 #else 00414 00415 #define OUTPUT_LEN 80 00416 00417 /* From a NIST PR=true test vector */ 00418 static const unsigned char entropy_pr[] = { 00419 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f, 00420 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11, 00421 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42, 00422 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3, 00423 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 }; 00424 static const unsigned char result_pr[OUTPUT_LEN] = { 00425 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39, 00426 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94, 00427 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54, 00428 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e, 00429 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab, 00430 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3, 00431 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 }; 00432 00433 /* From a NIST PR=false test vector */ 00434 static const unsigned char entropy_nopr[] = { 00435 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66, 00436 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8, 00437 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3, 00438 0xe9, 0x9d, 0xfe, 0xdf }; 00439 static const unsigned char result_nopr[OUTPUT_LEN] = { 00440 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f, 00441 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6, 00442 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a, 00443 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec, 00444 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd, 00445 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49, 00446 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 }; 00447 00448 /* "Entropy" from buffer */ 00449 static size_t test_offset; 00450 static int hmac_drbg_self_test_entropy( void *data, 00451 unsigned char *buf, size_t len ) 00452 { 00453 const unsigned char *p = data; 00454 memcpy( buf, p + test_offset, len ); 00455 test_offset += len; 00456 return( 0 ); 00457 } 00458 00459 #define CHK( c ) if( (c) != 0 ) \ 00460 { \ 00461 if( verbose != 0 ) \ 00462 mbedtls_printf( "failed\n" ); \ 00463 return( 1 ); \ 00464 } 00465 00466 /* 00467 * Checkup routine for HMAC_DRBG with SHA-1 00468 */ 00469 int mbedtls_hmac_drbg_self_test( int verbose ) 00470 { 00471 mbedtls_hmac_drbg_context ctx; 00472 unsigned char buf[OUTPUT_LEN]; 00473 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); 00474 00475 mbedtls_hmac_drbg_init( &ctx ); 00476 00477 /* 00478 * PR = True 00479 */ 00480 if( verbose != 0 ) 00481 mbedtls_printf( " HMAC_DRBG (PR = True) : " ); 00482 00483 test_offset = 0; 00484 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info, 00485 hmac_drbg_self_test_entropy, (void *) entropy_pr, 00486 NULL, 0 ) ); 00487 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON ); 00488 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); 00489 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); 00490 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) ); 00491 mbedtls_hmac_drbg_free( &ctx ); 00492 00493 mbedtls_hmac_drbg_free( &ctx ); 00494 00495 if( verbose != 0 ) 00496 mbedtls_printf( "passed\n" ); 00497 00498 /* 00499 * PR = False 00500 */ 00501 if( verbose != 0 ) 00502 mbedtls_printf( " HMAC_DRBG (PR = False) : " ); 00503 00504 mbedtls_hmac_drbg_init( &ctx ); 00505 00506 test_offset = 0; 00507 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info, 00508 hmac_drbg_self_test_entropy, (void *) entropy_nopr, 00509 NULL, 0 ) ); 00510 CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) ); 00511 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); 00512 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); 00513 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) ); 00514 mbedtls_hmac_drbg_free( &ctx ); 00515 00516 mbedtls_hmac_drbg_free( &ctx ); 00517 00518 if( verbose != 0 ) 00519 mbedtls_printf( "passed\n" ); 00520 00521 if( verbose != 0 ) 00522 mbedtls_printf( "\n" ); 00523 00524 return( 0 ); 00525 } 00526 #endif /* MBEDTLS_SHA1_C */ 00527 #endif /* MBEDTLS_SELF_TEST */ 00528 00529 #endif /* MBEDTLS_HMAC_DRBG_C */
Generated on Wed Jul 13 2022 20:34:20 by 1.7.2