xref: /optee_os/lib/libmbedtls/mbedtls/library/hmac_drbg.c (revision 5b25c76ac40f830867e3d60800120ffd7874e8dc)
1 // SPDX-License-Identifier: Apache-2.0
2 /*
3  *  HMAC_DRBG implementation (NIST SP 800-90)
4  *
5  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
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  */
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  */
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)
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  */
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  * Internal function used both for seeding and reseeding the DRBG.
153  * Comments starting with arabic numbers refer to section 10.1.2.4
154  * of SP800-90A, while roman numbers refer to section 9.2.
155  */
156 static int hmac_drbg_reseed_core( mbedtls_hmac_drbg_context *ctx,
157                                   const unsigned char *additional, size_t len,
158                                   int use_nonce )
159 {
160     unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
161     size_t seedlen = 0;
162     int ret;
163 
164     {
165         size_t total_entropy_len;
166 
167         if( use_nonce == 0 )
168             total_entropy_len = ctx->entropy_len;
169         else
170             total_entropy_len = ctx->entropy_len * 3 / 2;
171 
172         /* III. Check input length */
173         if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
174             total_entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT )
175         {
176             return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
177         }
178     }
179 
180     memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
181 
182     /* IV. Gather entropy_len bytes of entropy for the seed */
183     if( ( ret = ctx->f_entropy( ctx->p_entropy,
184                                 seed, ctx->entropy_len ) ) != 0 )
185     {
186         return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
187     }
188     seedlen += ctx->entropy_len;
189 
190     /* For initial seeding, allow adding of nonce generated
191      * from the entropy source. See Sect 8.6.7 in SP800-90A. */
192     if( use_nonce )
193     {
194         /* Note: We don't merge the two calls to f_entropy() in order
195          *       to avoid requesting too much entropy from f_entropy()
196          *       at once. Specifically, if the underlying digest is not
197          *       SHA-1, 3 / 2 * entropy_len is at least 36 Bytes, which
198          *       is larger than the maximum of 32 Bytes that our own
199          *       entropy source implementation can emit in a single
200          *       call in configurations disabling SHA-512. */
201         if( ( ret = ctx->f_entropy( ctx->p_entropy,
202                                     seed + seedlen,
203                                     ctx->entropy_len / 2 ) ) != 0 )
204         {
205             return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
206         }
207 
208         seedlen += ctx->entropy_len / 2;
209     }
210 
211 
212     /* 1. Concatenate entropy and additional data if any */
213     if( additional != NULL && len != 0 )
214     {
215         memcpy( seed + seedlen, additional, len );
216         seedlen += len;
217     }
218 
219     /* 2. Update state */
220     if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, seed, seedlen ) ) != 0 )
221         goto exit;
222 
223     /* 3. Reset reseed_counter */
224     ctx->reseed_counter = 1;
225 
226 exit:
227     /* 4. Done */
228     mbedtls_platform_zeroize( seed, seedlen );
229     return( ret );
230 }
231 
232 /*
233  * HMAC_DRBG reseeding: 10.1.2.4 + 9.2
234  */
235 int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
236                       const unsigned char *additional, size_t len )
237 {
238     return( hmac_drbg_reseed_core( ctx, additional, len, 0 ) );
239 }
240 
241 /*
242  * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
243  *
244  * The nonce is not passed as a separate parameter but extracted
245  * from the entropy source as suggested in 8.6.7.
246  */
247 int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
248                     const mbedtls_md_info_t * md_info,
249                     int (*f_entropy)(void *, unsigned char *, size_t),
250                     void *p_entropy,
251                     const unsigned char *custom,
252                     size_t len )
253 {
254     int ret;
255     size_t md_size;
256 
257     if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
258         return( ret );
259 
260     md_size = mbedtls_md_get_size( md_info );
261 
262     /*
263      * Set initial working state.
264      * Use the V memory location, which is currently all 0, to initialize the
265      * MD context with an all-zero key. Then set V to its initial value.
266      */
267     if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ) ) != 0 )
268         return( ret );
269     memset( ctx->V, 0x01, md_size );
270 
271     ctx->f_entropy = f_entropy;
272     ctx->p_entropy = p_entropy;
273 
274     ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
275 
276     if( ctx->entropy_len == 0 )
277     {
278         /*
279          * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
280          * each hash function, then according to SP800-90A rev1 10.1 table 2,
281          * min_entropy_len (in bits) is security_strength.
282          *
283          * (This also matches the sizes used in the NIST test vectors.)
284          */
285         ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
286                            md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
287                            32;  /* better (256+) -> 256 bits */
288     }
289 
290     if( ( ret = hmac_drbg_reseed_core( ctx, custom, len,
291                                        1 /* add nonce */ ) ) != 0 )
292     {
293         return( ret );
294     }
295 
296     return( 0 );
297 }
298 
299 /*
300  * Set prediction resistance
301  */
302 void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
303                                           int resistance )
304 {
305     ctx->prediction_resistance = resistance;
306 }
307 
308 /*
309  * Set entropy length grabbed for seeding
310  */
311 void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
312 {
313     ctx->entropy_len = len;
314 }
315 
316 /*
317  * Set reseed interval
318  */
319 void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval )
320 {
321     ctx->reseed_interval = interval;
322 }
323 
324 /*
325  * HMAC_DRBG random function with optional additional data:
326  * 10.1.2.5 (arabic) + 9.3 (Roman)
327  */
328 int mbedtls_hmac_drbg_random_with_add( void *p_rng,
329                                unsigned char *output, size_t out_len,
330                                const unsigned char *additional, size_t add_len )
331 {
332     int ret;
333     mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
334     size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
335     size_t left = out_len;
336     unsigned char *out = output;
337 
338     /* II. Check request length */
339     if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST )
340         return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
341 
342     /* III. Check input length */
343     if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
344         return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
345 
346     /* 1. (aka VII and IX) Check reseed counter and PR */
347     if( ctx->f_entropy != NULL && /* For no-reseeding instances */
348         ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
349           ctx->reseed_counter > ctx->reseed_interval ) )
350     {
351         if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
352             return( ret );
353 
354         add_len = 0; /* VII.4 */
355     }
356 
357     /* 2. Use additional data if any */
358     if( additional != NULL && add_len != 0 )
359     {
360         if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
361                                                   additional, add_len ) ) != 0 )
362             goto exit;
363     }
364 
365     /* 3, 4, 5. Generate bytes */
366     while( left != 0 )
367     {
368         size_t use_len = left > md_len ? md_len : left;
369 
370         if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
371             goto exit;
372         if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
373                                             ctx->V, md_len ) ) != 0 )
374             goto exit;
375         if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
376             goto exit;
377 
378         memcpy( out, ctx->V, use_len );
379         out += use_len;
380         left -= use_len;
381     }
382 
383     /* 6. Update */
384     if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
385                                               additional, add_len ) ) != 0 )
386         goto exit;
387 
388     /* 7. Update reseed counter */
389     ctx->reseed_counter++;
390 
391 exit:
392     /* 8. Done */
393     return( ret );
394 }
395 
396 /*
397  * HMAC_DRBG random function
398  */
399 int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
400 {
401     int ret;
402     mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
403 
404 #if defined(MBEDTLS_THREADING_C)
405     if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
406         return( ret );
407 #endif
408 
409     ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
410 
411 #if defined(MBEDTLS_THREADING_C)
412     if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
413         return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
414 #endif
415 
416     return( ret );
417 }
418 
419 /*
420  * Free an HMAC_DRBG context
421  */
422 void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
423 {
424     if( ctx == NULL )
425         return;
426 
427 #if defined(MBEDTLS_THREADING_C)
428     mbedtls_mutex_free( &ctx->mutex );
429 #endif
430     mbedtls_md_free( &ctx->md_ctx );
431     mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
432 }
433 
434 #if defined(MBEDTLS_FS_IO)
435 int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
436 {
437     int ret;
438     FILE *f;
439     unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
440 
441     if( ( f = fopen( path, "wb" ) ) == NULL )
442         return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
443 
444     if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
445         goto exit;
446 
447     if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
448     {
449         ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
450         goto exit;
451     }
452 
453     ret = 0;
454 
455 exit:
456     fclose( f );
457     mbedtls_platform_zeroize( buf, sizeof( buf ) );
458 
459     return( ret );
460 }
461 
462 int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
463 {
464     int ret = 0;
465     FILE *f = NULL;
466     size_t n;
467     unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
468     unsigned char c;
469 
470     if( ( f = fopen( path, "rb" ) ) == NULL )
471         return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
472 
473     n = fread( buf, 1, sizeof( buf ), f );
474     if( fread( &c, 1, 1, f ) != 0 )
475     {
476         ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
477         goto exit;
478     }
479     if( n == 0 || ferror( f ) )
480     {
481         ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
482         goto exit;
483     }
484     fclose( f );
485     f = NULL;
486 
487     ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n );
488 
489 exit:
490     mbedtls_platform_zeroize( buf, sizeof( buf ) );
491     if( f != NULL )
492         fclose( f );
493     if( ret != 0 )
494         return( ret );
495     return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
496 }
497 #endif /* MBEDTLS_FS_IO */
498 
499 
500 #if defined(MBEDTLS_SELF_TEST)
501 
502 #if !defined(MBEDTLS_SHA1_C)
503 /* Dummy checkup routine */
504 int mbedtls_hmac_drbg_self_test( int verbose )
505 {
506     (void) verbose;
507     return( 0 );
508 }
509 #else
510 
511 #define OUTPUT_LEN  80
512 
513 /* From a NIST PR=true test vector */
514 static const unsigned char entropy_pr[] = {
515     0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
516     0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
517     0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
518     0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
519     0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
520 static const unsigned char result_pr[OUTPUT_LEN] = {
521     0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
522     0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
523     0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
524     0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
525     0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
526     0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
527     0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
528 
529 /* From a NIST PR=false test vector */
530 static const unsigned char entropy_nopr[] = {
531     0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
532     0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
533     0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
534     0xe9, 0x9d, 0xfe, 0xdf };
535 static const unsigned char result_nopr[OUTPUT_LEN] = {
536     0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
537     0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
538     0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
539     0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
540     0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
541     0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
542     0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
543 
544 /* "Entropy" from buffer */
545 static size_t test_offset;
546 static int hmac_drbg_self_test_entropy( void *data,
547                                         unsigned char *buf, size_t len )
548 {
549     const unsigned char *p = data;
550     memcpy( buf, p + test_offset, len );
551     test_offset += len;
552     return( 0 );
553 }
554 
555 #define CHK( c )    if( (c) != 0 )                          \
556                     {                                       \
557                         if( verbose != 0 )                  \
558                             mbedtls_printf( "failed\n" );  \
559                         return( 1 );                        \
560                     }
561 
562 /*
563  * Checkup routine for HMAC_DRBG with SHA-1
564  */
565 int mbedtls_hmac_drbg_self_test( int verbose )
566 {
567     mbedtls_hmac_drbg_context ctx;
568     unsigned char buf[OUTPUT_LEN];
569     const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
570 
571     mbedtls_hmac_drbg_init( &ctx );
572 
573     /*
574      * PR = True
575      */
576     if( verbose != 0 )
577         mbedtls_printf( "  HMAC_DRBG (PR = True) : " );
578 
579     test_offset = 0;
580     CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
581                          hmac_drbg_self_test_entropy, (void *) entropy_pr,
582                          NULL, 0 ) );
583     mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
584     CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
585     CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
586     CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
587     mbedtls_hmac_drbg_free( &ctx );
588 
589     mbedtls_hmac_drbg_free( &ctx );
590 
591     if( verbose != 0 )
592         mbedtls_printf( "passed\n" );
593 
594     /*
595      * PR = False
596      */
597     if( verbose != 0 )
598         mbedtls_printf( "  HMAC_DRBG (PR = False) : " );
599 
600     mbedtls_hmac_drbg_init( &ctx );
601 
602     test_offset = 0;
603     CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
604                          hmac_drbg_self_test_entropy, (void *) entropy_nopr,
605                          NULL, 0 ) );
606     CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
607     CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
608     CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
609     CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
610     mbedtls_hmac_drbg_free( &ctx );
611 
612     mbedtls_hmac_drbg_free( &ctx );
613 
614     if( verbose != 0 )
615         mbedtls_printf( "passed\n" );
616 
617     if( verbose != 0 )
618         mbedtls_printf( "\n" );
619 
620     return( 0 );
621 }
622 #endif /* MBEDTLS_SHA1_C */
623 #endif /* MBEDTLS_SELF_TEST */
624 
625 #endif /* MBEDTLS_HMAC_DRBG_C */
626