Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

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