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