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