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