source: azure_iot_hub_mbedtls/trunk/mbedtls-2.16.1/library/hmac_drbg.c@ 398

Last change on this file since 398 was 398, checked in by coas-nagasima, 5 years ago

mbedTLS版Azure IoT Hub接続サンプルのソースコードを追加

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