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