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