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