1 /*
2  *  HMAC_DRBG implementation (NIST SP 800-90)
3  *
4  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5  *  SPDX-License-Identifier: Apache-2.0
6  *
7  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
8  *  not use this file except in compliance with the License.
9  *  You may obtain a copy of the License at
10  *
11  *  http://www.apache.org/licenses/LICENSE-2.0
12  *
13  *  Unless required by applicable law or agreed to in writing, software
14  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  *  See the License for the specific language governing permissions and
17  *  limitations under the License.
18  *
19  *  This file is part of mbed TLS (https://tls.mbed.org)
20  */
21 
22 /*
23  *  The NIST SP 800-90A DRBGs are described in the following publication.
24  *  http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
25  *  References below are based on rev. 1 (January 2012).
26  */
27 
28 #if !defined(MBEDTLS_CONFIG_FILE)
29 #include "mbedtls/config.h"
30 #else
31 #include MBEDTLS_CONFIG_FILE
32 #endif
33 
34 #if defined(MBEDTLS_HMAC_DRBG_C)
35 
36 #include "mbedtls/hmac_drbg.h"
37 #include "mbedtls/platform_util.h"
38 
39 #include <string.h>
40 
41 #if defined(MBEDTLS_FS_IO)
42 #include <stdio.h>
43 #endif
44 
45 #if defined(MBEDTLS_SELF_TEST)
46 #if defined(MBEDTLS_PLATFORM_C)
47 #include "mbedtls/platform.h"
48 #else
49 #include <stdio.h>
50 #define mbedtls_printf printf
51 #endif /* MBEDTLS_SELF_TEST */
52 #endif /* MBEDTLS_PLATFORM_C */
53 
54 /*
55  * HMAC_DRBG context initialization
56  */
mbedtls_hmac_drbg_init(mbedtls_hmac_drbg_context * ctx)57 void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx )
58 {
59     memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) );
60 
61 #if defined(MBEDTLS_THREADING_C)
62     mbedtls_mutex_init( &ctx->mutex );
63 #endif
64 }
65 
66 /*
67  * HMAC_DRBG update, using optional additional data (10.1.2.2)
68  */
mbedtls_hmac_drbg_update_ret(mbedtls_hmac_drbg_context * ctx,const unsigned char * additional,size_t add_len)69 int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx,
70                                   const unsigned char *additional,
71                                   size_t add_len )
72 {
73     size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
74     unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
75     unsigned char sep[1];
76     unsigned char K[MBEDTLS_MD_MAX_SIZE];
77     int ret = 0;
78 
79     for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
80     {
81         /* Step 1 or 4 */
82         if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
83             goto exit;
84         if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
85                                             ctx->V, md_len ) ) != 0 )
86             goto exit;
87         if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
88                                             sep, 1 ) ) != 0 )
89             goto exit;
90         if( rounds == 2 )
91         {
92             if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
93                                                 additional, add_len ) ) != 0 )
94             goto exit;
95         }
96         if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, K ) ) != 0 )
97             goto exit;
98 
99         /* Step 2 or 5 */
100         if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ) ) != 0 )
101             goto exit;
102         if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
103                                             ctx->V, md_len ) ) != 0 )
104             goto exit;
105         if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
106             goto exit;
107     }
108 
109 exit:
110     mbedtls_platform_zeroize( K, sizeof( K ) );
111     return( ret );
112 }
113 
114 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
mbedtls_hmac_drbg_update(mbedtls_hmac_drbg_context * ctx,const unsigned char * additional,size_t add_len)115 void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
116                                const unsigned char *additional,
117                                size_t add_len )
118 {
119     (void) mbedtls_hmac_drbg_update_ret( ctx, additional, add_len );
120 }
121 #endif /* MBEDTLS_DEPRECATED_REMOVED */
122 
123 /*
124  * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
125  */
mbedtls_hmac_drbg_seed_buf(mbedtls_hmac_drbg_context * ctx,const mbedtls_md_info_t * md_info,const unsigned char * data,size_t data_len)126 int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
127                         const mbedtls_md_info_t * md_info,
128                         const unsigned char *data, size_t data_len )
129 {
130     int ret;
131 
132     if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
133         return( ret );
134 
135     /*
136      * Set initial working state.
137      * Use the V memory location, which is currently all 0, to initialize the
138      * MD context with an all-zero key. Then set V to its initial value.
139      */
140     if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V,
141                                         mbedtls_md_get_size( md_info ) ) ) != 0 )
142         return( ret );
143     memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) );
144 
145     if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, data, data_len ) ) != 0 )
146         return( ret );
147 
148     return( 0 );
149 }
150 
151 /*
152  * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
153  */
mbedtls_hmac_drbg_reseed(mbedtls_hmac_drbg_context * ctx,const unsigned char * additional,size_t len)154 int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
155                       const unsigned char *additional, size_t len )
156 {
157     unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
158     size_t seedlen;
159     int ret;
160 
161     /* III. Check input length */
162     if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
163         ctx->entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT )
164     {
165         return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
166     }
167 
168     memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
169 
170     /* IV. Gather entropy_len bytes of entropy for the seed */
171     if( ( ret = ctx->f_entropy( ctx->p_entropy,
172                                 seed, ctx->entropy_len ) ) != 0 )
173         return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
174 
175     seedlen = ctx->entropy_len;
176 
177     /* 1. Concatenate entropy and additional data if any */
178     if( additional != NULL && len != 0 )
179     {
180         memcpy( seed + seedlen, additional, len );
181         seedlen += len;
182     }
183 
184     /* 2. Update state */
185     if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, seed, seedlen ) ) != 0 )
186         goto exit;
187 
188     /* 3. Reset reseed_counter */
189     ctx->reseed_counter = 1;
190 
191 exit:
192     /* 4. Done */
193     mbedtls_platform_zeroize( seed, seedlen );
194     return( ret );
195 }
196 
197 /*
198  * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
199  */
mbedtls_hmac_drbg_seed(mbedtls_hmac_drbg_context * ctx,const mbedtls_md_info_t * md_info,int (* f_entropy)(void *,unsigned char *,size_t),void * p_entropy,const unsigned char * custom,size_t len)200 int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
201                     const mbedtls_md_info_t * md_info,
202                     int (*f_entropy)(void *, unsigned char *, size_t),
203                     void *p_entropy,
204                     const unsigned char *custom,
205                     size_t len )
206 {
207     int ret;
208     size_t entropy_len, md_size;
209 
210     if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
211         return( ret );
212 
213     md_size = mbedtls_md_get_size( md_info );
214 
215     /*
216      * Set initial working state.
217      * Use the V memory location, which is currently all 0, to initialize the
218      * MD context with an all-zero key. Then set V to its initial value.
219      */
220     if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ) ) != 0 )
221         return( ret );
222     memset( ctx->V, 0x01, md_size );
223 
224     ctx->f_entropy = f_entropy;
225     ctx->p_entropy = p_entropy;
226 
227     ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
228 
229     /*
230      * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
231      * each hash function, then according to SP800-90A rev1 10.1 table 2,
232      * min_entropy_len (in bits) is security_strength.
233      *
234      * (This also matches the sizes used in the NIST test vectors.)
235      */
236     entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
237                   md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
238                                   32;  /* better (256+) -> 256 bits */
239 
240     /*
241      * For initialisation, use more entropy to emulate a nonce
242      * (Again, matches test vectors.)
243      */
244     ctx->entropy_len = entropy_len * 3 / 2;
245 
246     if( ( ret = mbedtls_hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
247         return( ret );
248 
249     ctx->entropy_len = entropy_len;
250 
251     return( 0 );
252 }
253 
254 /*
255  * Set prediction resistance
256  */
mbedtls_hmac_drbg_set_prediction_resistance(mbedtls_hmac_drbg_context * ctx,int resistance)257 void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
258                                           int resistance )
259 {
260     ctx->prediction_resistance = resistance;
261 }
262 
263 /*
264  * Set entropy length grabbed for reseeds
265  */
mbedtls_hmac_drbg_set_entropy_len(mbedtls_hmac_drbg_context * ctx,size_t len)266 void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
267 {
268     ctx->entropy_len = len;
269 }
270 
271 /*
272  * Set reseed interval
273  */
mbedtls_hmac_drbg_set_reseed_interval(mbedtls_hmac_drbg_context * ctx,int interval)274 void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval )
275 {
276     ctx->reseed_interval = interval;
277 }
278 
279 /*
280  * HMAC_DRBG random function with optional additional data:
281  * 10.1.2.5 (arabic) + 9.3 (Roman)
282  */
mbedtls_hmac_drbg_random_with_add(void * p_rng,unsigned char * output,size_t out_len,const unsigned char * additional,size_t add_len)283 int mbedtls_hmac_drbg_random_with_add( void *p_rng,
284                                unsigned char *output, size_t out_len,
285                                const unsigned char *additional, size_t add_len )
286 {
287     int ret;
288     mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
289     size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
290     size_t left = out_len;
291     unsigned char *out = output;
292 
293     /* II. Check request length */
294     if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST )
295         return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
296 
297     /* III. Check input length */
298     if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
299         return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
300 
301     /* 1. (aka VII and IX) Check reseed counter and PR */
302     if( ctx->f_entropy != NULL && /* For no-reseeding instances */
303         ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
304           ctx->reseed_counter > ctx->reseed_interval ) )
305     {
306         if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
307             return( ret );
308 
309         add_len = 0; /* VII.4 */
310     }
311 
312     /* 2. Use additional data if any */
313     if( additional != NULL && add_len != 0 )
314     {
315         if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
316                                                   additional, add_len ) ) != 0 )
317             goto exit;
318     }
319 
320     /* 3, 4, 5. Generate bytes */
321     while( left != 0 )
322     {
323         size_t use_len = left > md_len ? md_len : left;
324 
325         if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
326             goto exit;
327         if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
328                                             ctx->V, md_len ) ) != 0 )
329             goto exit;
330         if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
331             goto exit;
332 
333         use_len = (use_len < MBEDTLS_MD_MAX_SIZE) ? use_len : MBEDTLS_MD_MAX_SIZE;
334         memcpy( out, ctx->V, use_len );
335         out += use_len;
336         left -= use_len;
337     }
338 
339     /* 6. Update */
340     if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
341                                               additional, add_len ) ) != 0 )
342         goto exit;
343 
344     /* 7. Update reseed counter */
345     ctx->reseed_counter++;
346 
347 exit:
348     /* 8. Done */
349     return( ret );
350 }
351 
352 /*
353  * HMAC_DRBG random function
354  */
mbedtls_hmac_drbg_random(void * p_rng,unsigned char * output,size_t out_len)355 int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
356 {
357     int ret;
358     mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
359 
360 #if defined(MBEDTLS_THREADING_C)
361     if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
362         return( ret );
363 #endif
364 
365     ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
366 
367 #if defined(MBEDTLS_THREADING_C)
368     if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
369         return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
370 #endif
371 
372     return( ret );
373 }
374 
375 /*
376  * Free an HMAC_DRBG context
377  */
mbedtls_hmac_drbg_free(mbedtls_hmac_drbg_context * ctx)378 void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
379 {
380     if( ctx == NULL )
381         return;
382 
383 #if defined(MBEDTLS_THREADING_C)
384     mbedtls_mutex_free( &ctx->mutex );
385 #endif
386     mbedtls_md_free( &ctx->md_ctx );
387     mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
388 }
389 
390 #if defined(MBEDTLS_FS_IO)
mbedtls_hmac_drbg_write_seed_file(mbedtls_hmac_drbg_context * ctx,const char * path)391 int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
392 {
393     int ret;
394     FILE *f;
395     unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
396 
397     if( ( f = fopen( path, "wb" ) ) == NULL )
398         return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
399 
400     if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
401         goto exit;
402 
403     if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
404     {
405         ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
406         goto exit;
407     }
408 
409     ret = 0;
410 
411 exit:
412     fclose( f );
413     mbedtls_platform_zeroize( buf, sizeof( buf ) );
414 
415     return( ret );
416 }
417 
mbedtls_hmac_drbg_update_seed_file(mbedtls_hmac_drbg_context * ctx,const char * path)418 int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
419 {
420     int ret = 0;
421     FILE *f = NULL;
422     size_t n;
423     unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
424     unsigned char c;
425 
426     if( ( f = fopen( path, "rb" ) ) == NULL )
427         return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
428 
429     n = fread( buf, 1, sizeof( buf ), f );
430     if( fread( &c, 1, 1, f ) != 0 )
431     {
432         ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
433         goto exit;
434     }
435     if( n == 0 || ferror( f ) )
436     {
437         ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
438         goto exit;
439     }
440     fclose( f );
441     f = NULL;
442 
443     ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n );
444 
445 exit:
446     mbedtls_platform_zeroize( buf, sizeof( buf ) );
447     if( f != NULL )
448         fclose( f );
449     if( ret != 0 )
450         return( ret );
451     return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
452 }
453 #endif /* MBEDTLS_FS_IO */
454 
455 
456 #if defined(MBEDTLS_SELF_TEST)
457 
458 #if !defined(MBEDTLS_SHA1_C)
459 /* Dummy checkup routine */
mbedtls_hmac_drbg_self_test(int verbose)460 int mbedtls_hmac_drbg_self_test( int verbose )
461 {
462     (void) verbose;
463     return( 0 );
464 }
465 #else
466 
467 #define OUTPUT_LEN  80
468 
469 /* From a NIST PR=true test vector */
470 static const unsigned char entropy_pr[] = {
471     0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
472     0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
473     0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
474     0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
475     0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
476 static const unsigned char result_pr[OUTPUT_LEN] = {
477     0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
478     0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
479     0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
480     0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
481     0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
482     0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
483     0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
484 
485 /* From a NIST PR=false test vector */
486 static const unsigned char entropy_nopr[] = {
487     0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
488     0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
489     0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
490     0xe9, 0x9d, 0xfe, 0xdf };
491 static const unsigned char result_nopr[OUTPUT_LEN] = {
492     0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
493     0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
494     0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
495     0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
496     0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
497     0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
498     0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
499 
500 /* "Entropy" from buffer */
501 static size_t test_offset;
hmac_drbg_self_test_entropy(void * data,unsigned char * buf,size_t len)502 static int hmac_drbg_self_test_entropy( void *data,
503                                         unsigned char *buf, size_t len )
504 {
505     const unsigned char *p = data;
506     memcpy( buf, p + test_offset, len );
507     test_offset += len;
508     return( 0 );
509 }
510 
511 #define CHK( c )    if( (c) != 0 )                          \
512                     {                                       \
513                         if( verbose != 0 )                  \
514                             mbedtls_printf( "failed\n" );  \
515                         return( 1 );                        \
516                     }
517 
518 /*
519  * Checkup routine for HMAC_DRBG with SHA-1
520  */
mbedtls_hmac_drbg_self_test(int verbose)521 int mbedtls_hmac_drbg_self_test( int verbose )
522 {
523     mbedtls_hmac_drbg_context ctx;
524     unsigned char buf[OUTPUT_LEN];
525     const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
526 
527     mbedtls_hmac_drbg_init( &ctx );
528 
529     /*
530      * PR = True
531      */
532     if( verbose != 0 )
533         mbedtls_printf( "  HMAC_DRBG (PR = True) : " );
534 
535     test_offset = 0;
536     CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
537                          hmac_drbg_self_test_entropy, (void *) entropy_pr,
538                          NULL, 0 ) );
539     mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
540     CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
541     CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
542     CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
543     mbedtls_hmac_drbg_free( &ctx );
544 
545     mbedtls_hmac_drbg_free( &ctx );
546 
547     if( verbose != 0 )
548         mbedtls_printf( "passed\n" );
549 
550     /*
551      * PR = False
552      */
553     if( verbose != 0 )
554         mbedtls_printf( "  HMAC_DRBG (PR = False) : " );
555 
556     mbedtls_hmac_drbg_init( &ctx );
557 
558     test_offset = 0;
559     CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
560                          hmac_drbg_self_test_entropy, (void *) entropy_nopr,
561                          NULL, 0 ) );
562     CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
563     CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
564     CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
565     CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
566     mbedtls_hmac_drbg_free( &ctx );
567 
568     mbedtls_hmac_drbg_free( &ctx );
569 
570     if( verbose != 0 )
571         mbedtls_printf( "passed\n" );
572 
573     if( verbose != 0 )
574         mbedtls_printf( "\n" );
575 
576     return( 0 );
577 }
578 #endif /* MBEDTLS_SHA1_C */
579 #endif /* MBEDTLS_SELF_TEST */
580 
581 #endif /* MBEDTLS_HMAC_DRBG_C */
582