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 #if defined(MBEDTLS_THREADING_C)
59     mbedtls_mutex_init( &ctx->mutex );
60 #endif
61 }
62 
63 /*
64  * HMAC_DRBG update, using optional additional data (10.1.2.2)
65  */
mbedtls_hmac_drbg_update_ret(mbedtls_hmac_drbg_context * ctx,const unsigned char * additional,size_t add_len)66 int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx,
67                                   const unsigned char *additional,
68                                   size_t add_len )
69 {
70     size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
71     unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
72     unsigned char sep[1];
73     unsigned char K[MBEDTLS_MD_MAX_SIZE];
74     int ret = MBEDTLS_ERR_MD_BAD_INPUT_DATA;
75 
76     for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
77     {
78         /* Step 1 or 4 */
79         if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
80             goto exit;
81         if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
82                                             ctx->V, md_len ) ) != 0 )
83             goto exit;
84         if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
85                                             sep, 1 ) ) != 0 )
86             goto exit;
87         if( rounds == 2 )
88         {
89             if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
90                                                 additional, add_len ) ) != 0 )
91             goto exit;
92         }
93         if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, K ) ) != 0 )
94             goto exit;
95 
96         /* Step 2 or 5 */
97         if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ) ) != 0 )
98             goto exit;
99         if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
100                                             ctx->V, md_len ) ) != 0 )
101             goto exit;
102         if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
103             goto exit;
104     }
105 
106 exit:
107     mbedtls_platform_zeroize( K, sizeof( K ) );
108     return( ret );
109 }
110 
111 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
mbedtls_hmac_drbg_update(mbedtls_hmac_drbg_context * ctx,const unsigned char * additional,size_t add_len)112 void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
113                                const unsigned char *additional,
114                                size_t add_len )
115 {
116     (void) mbedtls_hmac_drbg_update_ret( ctx, additional, add_len );
117 }
118 #endif /* MBEDTLS_DEPRECATED_REMOVED */
119 
120 /*
121  * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
122  */
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)123 int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
124                         const mbedtls_md_info_t * md_info,
125                         const unsigned char *data, size_t data_len )
126 {
127     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
128 
129     if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
130         return( ret );
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     md_size = mbedtls_md_get_size( md_info );
258 
259     /*
260      * Set initial working state.
261      * Use the V memory location, which is currently all 0, to initialize the
262      * MD context with an all-zero key. Then set V to its initial value.
263      */
264     if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ) ) != 0 )
265         return( ret );
266     memset( ctx->V, 0x01, md_size );
267 
268     ctx->f_entropy = f_entropy;
269     ctx->p_entropy = p_entropy;
270 
271     if( ctx->entropy_len == 0 )
272     {
273         /*
274          * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
275          * each hash function, then according to SP800-90A rev1 10.1 table 2,
276          * min_entropy_len (in bits) is security_strength.
277          *
278          * (This also matches the sizes used in the NIST test vectors.)
279          */
280         ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
281                            md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
282                            32;  /* better (256+) -> 256 bits */
283     }
284 
285     if( ( ret = hmac_drbg_reseed_core( ctx, custom, len,
286                                        1 /* add nonce */ ) ) != 0 )
287     {
288         return( ret );
289     }
290 
291     return( 0 );
292 }
293 
294 /*
295  * Set prediction resistance
296  */
mbedtls_hmac_drbg_set_prediction_resistance(mbedtls_hmac_drbg_context * ctx,int resistance)297 void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
298                                           int resistance )
299 {
300     ctx->prediction_resistance = resistance;
301 }
302 
303 /*
304  * Set entropy length grabbed for seeding
305  */
mbedtls_hmac_drbg_set_entropy_len(mbedtls_hmac_drbg_context * ctx,size_t len)306 void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
307 {
308     ctx->entropy_len = len;
309 }
310 
311 /*
312  * Set reseed interval
313  */
mbedtls_hmac_drbg_set_reseed_interval(mbedtls_hmac_drbg_context * ctx,int interval)314 void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval )
315 {
316     ctx->reseed_interval = interval;
317 }
318 
319 /*
320  * HMAC_DRBG random function with optional additional data:
321  * 10.1.2.5 (arabic) + 9.3 (Roman)
322  */
mbedtls_hmac_drbg_random_with_add(void * p_rng,unsigned char * output,size_t out_len,const unsigned char * additional,size_t add_len)323 int mbedtls_hmac_drbg_random_with_add( void *p_rng,
324                                unsigned char *output, size_t out_len,
325                                const unsigned char *additional, size_t add_len )
326 {
327     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
328     mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
329     size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
330     size_t left = out_len;
331     unsigned char *out = output;
332 
333     /* II. Check request length */
334     if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST )
335         return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
336 
337     /* III. Check input length */
338     if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
339         return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
340 
341     /* 1. (aka VII and IX) Check reseed counter and PR */
342     if( ctx->f_entropy != NULL && /* For no-reseeding instances */
343         ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
344           ctx->reseed_counter > ctx->reseed_interval ) )
345     {
346         if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
347             return( ret );
348 
349         add_len = 0; /* VII.4 */
350     }
351 
352     /* 2. Use additional data if any */
353     if( additional != NULL && add_len != 0 )
354     {
355         if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
356                                                   additional, add_len ) ) != 0 )
357             goto exit;
358     }
359 
360     /* 3, 4, 5. Generate bytes */
361     while( left != 0 )
362     {
363         size_t use_len = left > md_len ? md_len : left;
364 
365         if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
366             goto exit;
367         if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
368                                             ctx->V, md_len ) ) != 0 )
369             goto exit;
370         if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
371             goto exit;
372 
373         memcpy( out, ctx->V, use_len );
374         out += use_len;
375         left -= use_len;
376     }
377 
378     /* 6. Update */
379     if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
380                                               additional, add_len ) ) != 0 )
381         goto exit;
382 
383     /* 7. Update reseed counter */
384     ctx->reseed_counter++;
385 
386 exit:
387     /* 8. Done */
388     return( ret );
389 }
390 
391 /*
392  * HMAC_DRBG random function
393  */
mbedtls_hmac_drbg_random(void * p_rng,unsigned char * output,size_t out_len)394 int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
395 {
396     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
397     mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
398 
399 #if defined(MBEDTLS_THREADING_C)
400     if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
401         return( ret );
402 #endif
403 
404     ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
405 
406 #if defined(MBEDTLS_THREADING_C)
407     if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
408         return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
409 #endif
410 
411     return( ret );
412 }
413 
414 /*
415  *  This function resets HMAC_DRBG context to the state immediately
416  *  after initial call of mbedtls_hmac_drbg_init().
417  */
mbedtls_hmac_drbg_free(mbedtls_hmac_drbg_context * ctx)418 void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
419 {
420     if( ctx == NULL )
421         return;
422 
423 #if defined(MBEDTLS_THREADING_C)
424     mbedtls_mutex_free( &ctx->mutex );
425 #endif
426     mbedtls_md_free( &ctx->md_ctx );
427     mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
428     ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
429 #if defined(MBEDTLS_THREADING_C)
430     mbedtls_mutex_init( &ctx->mutex );
431 #endif
432 }
433 
434 #if defined(MBEDTLS_FS_IO)
mbedtls_hmac_drbg_write_seed_file(mbedtls_hmac_drbg_context * ctx,const char * path)435 int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
436 {
437     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
438     FILE *f;
439     unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
440 
441     if( ( f = fopen( path, "wb" ) ) == NULL )
442         return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
443 
444     if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
445         goto exit;
446 
447     if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
448     {
449         ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
450         goto exit;
451     }
452 
453     ret = 0;
454 
455 exit:
456     fclose( f );
457     mbedtls_platform_zeroize( buf, sizeof( buf ) );
458 
459     return( ret );
460 }
461 
mbedtls_hmac_drbg_update_seed_file(mbedtls_hmac_drbg_context * ctx,const char * path)462 int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
463 {
464     int ret = 0;
465     FILE *f = NULL;
466     size_t n;
467     unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
468     unsigned char c;
469 
470     if( ( f = fopen( path, "rb" ) ) == NULL )
471         return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
472 
473     n = fread( buf, 1, sizeof( buf ), f );
474     if( fread( &c, 1, 1, f ) != 0 )
475     {
476         ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
477         goto exit;
478     }
479     if( n == 0 || ferror( f ) )
480     {
481         ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
482         goto exit;
483     }
484     fclose( f );
485     f = NULL;
486 
487     ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n );
488 
489 exit:
490     mbedtls_platform_zeroize( buf, sizeof( buf ) );
491     if( f != NULL )
492         fclose( f );
493     if( ret != 0 )
494         return( ret );
495     return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
496 }
497 #endif /* MBEDTLS_FS_IO */
498 
499 
500 #if defined(MBEDTLS_SELF_TEST)
501 
502 #if !defined(MBEDTLS_SHA1_C)
503 /* Dummy checkup routine */
mbedtls_hmac_drbg_self_test(int verbose)504 int mbedtls_hmac_drbg_self_test( int verbose )
505 {
506     (void) verbose;
507     return( 0 );
508 }
509 #else
510 
511 #define OUTPUT_LEN  80
512 
513 /* From a NIST PR=true test vector */
514 static const unsigned char entropy_pr[] = {
515     0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
516     0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
517     0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
518     0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
519     0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
520 static const unsigned char result_pr[OUTPUT_LEN] = {
521     0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
522     0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
523     0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
524     0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
525     0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
526     0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
527     0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
528 
529 /* From a NIST PR=false test vector */
530 static const unsigned char entropy_nopr[] = {
531     0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
532     0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
533     0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
534     0xe9, 0x9d, 0xfe, 0xdf };
535 static const unsigned char result_nopr[OUTPUT_LEN] = {
536     0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
537     0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
538     0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
539     0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
540     0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
541     0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
542     0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
543 
544 /* "Entropy" from buffer */
545 static size_t test_offset;
hmac_drbg_self_test_entropy(void * data,unsigned char * buf,size_t len)546 static int hmac_drbg_self_test_entropy( void *data,
547                                         unsigned char *buf, size_t len )
548 {
549     const unsigned char *p = data;
550     memcpy( buf, p + test_offset, len );
551     test_offset += len;
552     return( 0 );
553 }
554 
555 #define CHK( c )    if( (c) != 0 )                          \
556                     {                                       \
557                         if( verbose != 0 )                  \
558                             mbedtls_printf( "failed\n" );  \
559                         return( 1 );                        \
560                     }
561 
562 /*
563  * Checkup routine for HMAC_DRBG with SHA-1
564  */
mbedtls_hmac_drbg_self_test(int verbose)565 int mbedtls_hmac_drbg_self_test( int verbose )
566 {
567     mbedtls_hmac_drbg_context ctx;
568     unsigned char buf[OUTPUT_LEN];
569     const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
570 
571     mbedtls_hmac_drbg_init( &ctx );
572 
573     /*
574      * PR = True
575      */
576     if( verbose != 0 )
577         mbedtls_printf( "  HMAC_DRBG (PR = True) : " );
578 
579     test_offset = 0;
580     CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
581                          hmac_drbg_self_test_entropy, (void *) entropy_pr,
582                          NULL, 0 ) );
583     mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
584     CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
585     CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
586     CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
587     mbedtls_hmac_drbg_free( &ctx );
588 
589     mbedtls_hmac_drbg_free( &ctx );
590 
591     if( verbose != 0 )
592         mbedtls_printf( "passed\n" );
593 
594     /*
595      * PR = False
596      */
597     if( verbose != 0 )
598         mbedtls_printf( "  HMAC_DRBG (PR = False) : " );
599 
600     mbedtls_hmac_drbg_init( &ctx );
601 
602     test_offset = 0;
603     CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
604                          hmac_drbg_self_test_entropy, (void *) entropy_nopr,
605                          NULL, 0 ) );
606     CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
607     CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
608     CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
609     CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
610     mbedtls_hmac_drbg_free( &ctx );
611 
612     mbedtls_hmac_drbg_free( &ctx );
613 
614     if( verbose != 0 )
615         mbedtls_printf( "passed\n" );
616 
617     if( verbose != 0 )
618         mbedtls_printf( "\n" );
619 
620     return( 0 );
621 }
622 #endif /* MBEDTLS_SHA1_C */
623 #endif /* MBEDTLS_SELF_TEST */
624 
625 #endif /* MBEDTLS_HMAC_DRBG_C */
626