Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers hmac_drbg.c Source File

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     mbedtls_zeroize( buf, sizeof( buf ) );
00368 
00369     return( ret );
00370 }
00371 
00372 int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
00373 {
00374     int ret = 0;
00375     FILE *f;
00376     size_t n;
00377     unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
00378 
00379     if( ( f = fopen( path, "rb" ) ) == NULL )
00380         return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
00381 
00382     fseek( f, 0, SEEK_END );
00383     n = (size_t) ftell( f );
00384     fseek( f, 0, SEEK_SET );
00385 
00386     if( n > MBEDTLS_HMAC_DRBG_MAX_INPUT )
00387     {
00388         fclose( f );
00389         return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
00390     }
00391 
00392     if( fread( buf, 1, n, f ) != n )
00393         ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
00394     else
00395         mbedtls_hmac_drbg_update( ctx, buf, n );
00396 
00397     fclose( f );
00398 
00399     mbedtls_zeroize( buf, sizeof( buf ) );
00400 
00401     if( ret != 0 )
00402         return( ret );
00403 
00404     return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
00405 }
00406 #endif /* MBEDTLS_FS_IO */
00407 
00408 
00409 #if defined(MBEDTLS_SELF_TEST)
00410 
00411 #if !defined(MBEDTLS_SHA1_C)
00412 /* Dummy checkup routine */
00413 int mbedtls_hmac_drbg_self_test( int verbose )
00414 {
00415     (void) verbose;
00416     return( 0 );
00417 }
00418 #else
00419 
00420 #define OUTPUT_LEN  80
00421 
00422 /* From a NIST PR=true test vector */
00423 static const unsigned char entropy_pr[] = {
00424     0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
00425     0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
00426     0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
00427     0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
00428     0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
00429 static const unsigned char result_pr[OUTPUT_LEN] = {
00430     0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
00431     0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
00432     0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
00433     0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
00434     0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
00435     0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
00436     0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
00437 
00438 /* From a NIST PR=false test vector */
00439 static const unsigned char entropy_nopr[] = {
00440     0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
00441     0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
00442     0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
00443     0xe9, 0x9d, 0xfe, 0xdf };
00444 static const unsigned char result_nopr[OUTPUT_LEN] = {
00445     0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
00446     0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
00447     0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
00448     0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
00449     0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
00450     0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
00451     0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
00452 
00453 /* "Entropy" from buffer */
00454 static size_t test_offset;
00455 static int hmac_drbg_self_test_entropy( void *data,
00456                                         unsigned char *buf, size_t len )
00457 {
00458     const unsigned char *p = data;
00459     memcpy( buf, p + test_offset, len );
00460     test_offset += len;
00461     return( 0 );
00462 }
00463 
00464 #define CHK( c )    if( (c) != 0 )                          \
00465                     {                                       \
00466                         if( verbose != 0 )                  \
00467                             mbedtls_printf( "failed\n" );  \
00468                         return( 1 );                        \
00469                     }
00470 
00471 /*
00472  * Checkup routine for HMAC_DRBG with SHA-1
00473  */
00474 int mbedtls_hmac_drbg_self_test( int verbose )
00475 {
00476     mbedtls_hmac_drbg_context ctx;
00477     unsigned char buf[OUTPUT_LEN];
00478     const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
00479 
00480     mbedtls_hmac_drbg_init( &ctx );
00481 
00482     /*
00483      * PR = True
00484      */
00485     if( verbose != 0 )
00486         mbedtls_printf( "  HMAC_DRBG (PR = True) : " );
00487 
00488     test_offset = 0;
00489     CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
00490                          hmac_drbg_self_test_entropy, (void *) entropy_pr,
00491                          NULL, 0 ) );
00492     mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
00493     CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
00494     CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
00495     CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
00496     mbedtls_hmac_drbg_free( &ctx );
00497 
00498     mbedtls_hmac_drbg_free( &ctx );
00499 
00500     if( verbose != 0 )
00501         mbedtls_printf( "passed\n" );
00502 
00503     /*
00504      * PR = False
00505      */
00506     if( verbose != 0 )
00507         mbedtls_printf( "  HMAC_DRBG (PR = False) : " );
00508 
00509     mbedtls_hmac_drbg_init( &ctx );
00510 
00511     test_offset = 0;
00512     CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
00513                          hmac_drbg_self_test_entropy, (void *) entropy_nopr,
00514                          NULL, 0 ) );
00515     CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
00516     CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
00517     CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
00518     CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
00519     mbedtls_hmac_drbg_free( &ctx );
00520 
00521     mbedtls_hmac_drbg_free( &ctx );
00522 
00523     if( verbose != 0 )
00524         mbedtls_printf( "passed\n" );
00525 
00526     if( verbose != 0 )
00527         mbedtls_printf( "\n" );
00528 
00529     return( 0 );
00530 }
00531 #endif /* MBEDTLS_SHA1_C */
00532 #endif /* MBEDTLS_SELF_TEST */
00533 
00534 #endif /* MBEDTLS_HMAC_DRBG_C */