takashi kadono / Mbed OS Nucleo446_SSD1331

Dependencies:   ssd1331

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