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