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;
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         memcpy( out, ctx->V, use_len );
334         out += use_len;
335         left -= use_len;
336     }
337 
338     /* 6. Update */
339     if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
340                                               additional, add_len ) ) != 0 )
341         goto exit;
342 
343     /* 7. Update reseed counter */
344     ctx->reseed_counter++;
345 
346 exit:
347     /* 8. Done */
348     return( ret );
349 }
350 
351 /*
352  * HMAC_DRBG random function
353  */
mbedtls_hmac_drbg_random(void * p_rng,unsigned char * output,size_t out_len)354 int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
355 {
356     int ret;
357     mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
358 
359 #if defined(MBEDTLS_THREADING_C)
360     if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
361         return( ret );
362 #endif
363 
364     ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
365 
366 #if defined(MBEDTLS_THREADING_C)
367     if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
368         return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
369 #endif
370 
371     return( ret );
372 }
373 
374 /*
375  * Free an HMAC_DRBG context
376  */
mbedtls_hmac_drbg_free(mbedtls_hmac_drbg_context * ctx)377 void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
378 {
379     if( ctx == NULL )
380         return;
381 
382 #if defined(MBEDTLS_THREADING_C)
383     mbedtls_mutex_free( &ctx->mutex );
384 #endif
385     mbedtls_md_free( &ctx->md_ctx );
386     mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
387 }
388 
389 #if defined(MBEDTLS_FS_IO)
mbedtls_hmac_drbg_write_seed_file(mbedtls_hmac_drbg_context * ctx,const char * path)390 int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
391 {
392     int ret;
393     FILE *f;
394     unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
395 
396     if( ( f = fopen( path, "wb" ) ) == NULL )
397         return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
398 
399     if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
400         goto exit;
401 
402     if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
403     {
404         ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
405         goto exit;
406     }
407 
408     ret = 0;
409 
410 exit:
411     fclose( f );
412     mbedtls_platform_zeroize( buf, sizeof( buf ) );
413 
414     return( ret );
415 }
416 
mbedtls_hmac_drbg_update_seed_file(mbedtls_hmac_drbg_context * ctx,const char * path)417 int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
418 {
419     int ret = 0;
420     FILE *f = NULL;
421     size_t n;
422     unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
423     unsigned char c;
424 
425     if( ( f = fopen( path, "rb" ) ) == NULL )
426         return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
427 
428     n = fread( buf, 1, sizeof( buf ), f );
429     if( fread( &c, 1, 1, f ) != 0 )
430     {
431         ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
432         goto exit;
433     }
434     if( n == 0 || ferror( f ) )
435     {
436         ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
437         goto exit;
438     }
439     fclose( f );
440     f = NULL;
441 
442     ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n );
443 
444 exit:
445     mbedtls_platform_zeroize( buf, sizeof( buf ) );
446     if( f != NULL )
447         fclose( f );
448     if( ret != 0 )
449         return( ret );
450     return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
451 }
452 #endif /* MBEDTLS_FS_IO */
453 
454 
455 #if defined(MBEDTLS_SELF_TEST)
456 
457 #if !defined(MBEDTLS_SHA1_C)
458 /* Dummy checkup routine */
mbedtls_hmac_drbg_self_test(int verbose)459 int mbedtls_hmac_drbg_self_test( int verbose )
460 {
461     (void) verbose;
462     return( 0 );
463 }
464 #else
465 
466 #define OUTPUT_LEN  80
467 
468 /* From a NIST PR=true test vector */
469 static const unsigned char entropy_pr[] = {
470     0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
471     0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
472     0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
473     0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
474     0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
475 static const unsigned char result_pr[OUTPUT_LEN] = {
476     0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
477     0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
478     0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
479     0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
480     0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
481     0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
482     0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
483 
484 /* From a NIST PR=false test vector */
485 static const unsigned char entropy_nopr[] = {
486     0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
487     0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
488     0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
489     0xe9, 0x9d, 0xfe, 0xdf };
490 static const unsigned char result_nopr[OUTPUT_LEN] = {
491     0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
492     0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
493     0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
494     0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
495     0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
496     0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
497     0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
498 
499 /* "Entropy" from buffer */
500 static size_t test_offset;
hmac_drbg_self_test_entropy(void * data,unsigned char * buf,size_t len)501 static int hmac_drbg_self_test_entropy( void *data,
502                                         unsigned char *buf, size_t len )
503 {
504     const unsigned char *p = data;
505     memcpy( buf, p + test_offset, len );
506     test_offset += len;
507     return( 0 );
508 }
509 
510 #define CHK( c )    if( (c) != 0 )                          \
511                     {                                       \
512                         if( verbose != 0 )                  \
513                             mbedtls_printf( "failed\n" );  \
514                         return( 1 );                        \
515                     }
516 
517 /*
518  * Checkup routine for HMAC_DRBG with SHA-1
519  */
mbedtls_hmac_drbg_self_test(int verbose)520 int mbedtls_hmac_drbg_self_test( int verbose )
521 {
522     mbedtls_hmac_drbg_context ctx;
523     unsigned char buf[OUTPUT_LEN];
524     const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
525 
526     mbedtls_hmac_drbg_init( &ctx );
527 
528     /*
529      * PR = True
530      */
531     if( verbose != 0 )
532         mbedtls_printf( "  HMAC_DRBG (PR = True) : " );
533 
534     test_offset = 0;
535     CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
536                          hmac_drbg_self_test_entropy, (void *) entropy_pr,
537                          NULL, 0 ) );
538     mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
539     CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
540     CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
541     CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
542     mbedtls_hmac_drbg_free( &ctx );
543 
544     mbedtls_hmac_drbg_free( &ctx );
545 
546     if( verbose != 0 )
547         mbedtls_printf( "passed\n" );
548 
549     /*
550      * PR = False
551      */
552     if( verbose != 0 )
553         mbedtls_printf( "  HMAC_DRBG (PR = False) : " );
554 
555     mbedtls_hmac_drbg_init( &ctx );
556 
557     test_offset = 0;
558     CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
559                          hmac_drbg_self_test_entropy, (void *) entropy_nopr,
560                          NULL, 0 ) );
561     CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
562     CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
563     CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
564     CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
565     mbedtls_hmac_drbg_free( &ctx );
566 
567     mbedtls_hmac_drbg_free( &ctx );
568 
569     if( verbose != 0 )
570         mbedtls_printf( "passed\n" );
571 
572     if( verbose != 0 )
573         mbedtls_printf( "\n" );
574 
575     return( 0 );
576 }
577 #endif /* MBEDTLS_SHA1_C */
578 #endif /* MBEDTLS_SELF_TEST */
579 
580 #endif /* MBEDTLS_HMAC_DRBG_C */
581