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