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