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