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