blob: 3fce52dbfc3525f57742e3f4fc56d41a7d53c528 [file] [log] [blame]
Edison Aic6672fd2018-02-28 15:01:47 +08001// SPDX-License-Identifier: Apache-2.0
Jens Wiklander817466c2018-05-22 13:49:31 +02002/*
3 * HMAC_DRBG implementation (NIST SP 800-90)
4 *
5 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Jens Wiklander817466c2018-05-22 13:49:31 +02006 *
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"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010037#include "mbedtls/platform_util.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020038
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
Jens Wiklander817466c2018-05-22 13:49:31 +020054/*
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 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +010069int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx,
70 const unsigned char *additional,
71 size_t add_len )
Jens Wiklander817466c2018-05-22 13:49:31 +020072{
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];
Jens Wiklander3d3b0592019-03-20 15:30:29 +010077 int ret;
Jens Wiklander817466c2018-05-22 13:49:31 +020078
79 for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
80 {
81 /* Step 1 or 4 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +010082 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;
Jens Wiklander817466c2018-05-22 13:49:31 +020090 if( rounds == 2 )
Jens Wiklander3d3b0592019-03-20 15:30:29 +010091 {
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;
Jens Wiklander817466c2018-05-22 13:49:31 +020098
99 /* Step 2 or 5 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100100 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;
Jens Wiklander817466c2018-05-22 13:49:31 +0200107 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100108
109exit:
110 mbedtls_platform_zeroize( K, sizeof( K ) );
111 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200112}
113
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100114#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
Jens Wiklander817466c2018-05-22 13:49:31 +0200123/*
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 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100140 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V,
141 mbedtls_md_get_size( md_info ) ) ) != 0 )
142 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200143 memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) );
144
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100145 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, data, data_len ) ) != 0 )
146 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200147
148 return( 0 );
149}
150
151/*
Jerome Forissier5b25c762020-04-07 11:18:49 +0200152 * Internal function used both for seeding and reseeding the DRBG.
153 * Comments starting with arabic numbers refer to section 10.1.2.4
154 * of SP800-90A, while roman numbers refer to section 9.2.
Jens Wiklander817466c2018-05-22 13:49:31 +0200155 */
Jerome Forissier5b25c762020-04-07 11:18:49 +0200156static int hmac_drbg_reseed_core( mbedtls_hmac_drbg_context *ctx,
157 const unsigned char *additional, size_t len,
158 int use_nonce )
Jens Wiklander817466c2018-05-22 13:49:31 +0200159{
160 unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
Jerome Forissier5b25c762020-04-07 11:18:49 +0200161 size_t seedlen = 0;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100162 int ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200163
Jens Wiklander817466c2018-05-22 13:49:31 +0200164 {
Jerome Forissier5b25c762020-04-07 11:18:49 +0200165 size_t total_entropy_len;
166
167 if( use_nonce == 0 )
168 total_entropy_len = ctx->entropy_len;
169 else
170 total_entropy_len = ctx->entropy_len * 3 / 2;
171
172 /* III. Check input length */
173 if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
174 total_entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT )
175 {
176 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
177 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200178 }
179
180 memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
181
182 /* IV. Gather entropy_len bytes of entropy for the seed */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100183 if( ( ret = ctx->f_entropy( ctx->p_entropy,
184 seed, ctx->entropy_len ) ) != 0 )
Jerome Forissier5b25c762020-04-07 11:18:49 +0200185 {
Jens Wiklander817466c2018-05-22 13:49:31 +0200186 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
Jerome Forissier5b25c762020-04-07 11:18:49 +0200187 }
188 seedlen += ctx->entropy_len;
Jens Wiklander817466c2018-05-22 13:49:31 +0200189
Jerome Forissier5b25c762020-04-07 11:18:49 +0200190 /* For initial seeding, allow adding of nonce generated
191 * from the entropy source. See Sect 8.6.7 in SP800-90A. */
192 if( use_nonce )
193 {
194 /* Note: We don't merge the two calls to f_entropy() in order
195 * to avoid requesting too much entropy from f_entropy()
196 * at once. Specifically, if the underlying digest is not
197 * SHA-1, 3 / 2 * entropy_len is at least 36 Bytes, which
198 * is larger than the maximum of 32 Bytes that our own
199 * entropy source implementation can emit in a single
200 * call in configurations disabling SHA-512. */
201 if( ( ret = ctx->f_entropy( ctx->p_entropy,
202 seed + seedlen,
203 ctx->entropy_len / 2 ) ) != 0 )
204 {
205 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
206 }
207
208 seedlen += ctx->entropy_len / 2;
209 }
210
Jens Wiklander817466c2018-05-22 13:49:31 +0200211
212 /* 1. Concatenate entropy and additional data if any */
213 if( additional != NULL && len != 0 )
214 {
215 memcpy( seed + seedlen, additional, len );
216 seedlen += len;
217 }
218
219 /* 2. Update state */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100220 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, seed, seedlen ) ) != 0 )
221 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200222
223 /* 3. Reset reseed_counter */
224 ctx->reseed_counter = 1;
225
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100226exit:
Jens Wiklander817466c2018-05-22 13:49:31 +0200227 /* 4. Done */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100228 mbedtls_platform_zeroize( seed, seedlen );
229 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200230}
231
232/*
Jerome Forissier5b25c762020-04-07 11:18:49 +0200233 * HMAC_DRBG reseeding: 10.1.2.4 + 9.2
234 */
235int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
236 const unsigned char *additional, size_t len )
237{
238 return( hmac_drbg_reseed_core( ctx, additional, len, 0 ) );
239}
240
241/*
Jens Wiklander817466c2018-05-22 13:49:31 +0200242 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
Jerome Forissier5b25c762020-04-07 11:18:49 +0200243 *
244 * The nonce is not passed as a separate parameter but extracted
245 * from the entropy source as suggested in 8.6.7.
Jens Wiklander817466c2018-05-22 13:49:31 +0200246 */
247int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
248 const mbedtls_md_info_t * md_info,
249 int (*f_entropy)(void *, unsigned char *, size_t),
250 void *p_entropy,
251 const unsigned char *custom,
252 size_t len )
253{
254 int ret;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200255 size_t md_size;
Jens Wiklander817466c2018-05-22 13:49:31 +0200256
257 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
258 return( ret );
259
260 md_size = mbedtls_md_get_size( md_info );
261
262 /*
263 * Set initial working state.
264 * Use the V memory location, which is currently all 0, to initialize the
265 * MD context with an all-zero key. Then set V to its initial value.
266 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100267 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ) ) != 0 )
268 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200269 memset( ctx->V, 0x01, md_size );
270
271 ctx->f_entropy = f_entropy;
272 ctx->p_entropy = p_entropy;
273
274 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
275
Jerome Forissier5b25c762020-04-07 11:18:49 +0200276 if( ctx->entropy_len == 0 )
277 {
278 /*
279 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
280 * each hash function, then according to SP800-90A rev1 10.1 table 2,
281 * min_entropy_len (in bits) is security_strength.
282 *
283 * (This also matches the sizes used in the NIST test vectors.)
284 */
285 ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
286 md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
287 32; /* better (256+) -> 256 bits */
288 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200289
Jerome Forissier5b25c762020-04-07 11:18:49 +0200290 if( ( ret = hmac_drbg_reseed_core( ctx, custom, len,
291 1 /* add nonce */ ) ) != 0 )
292 {
Jens Wiklander817466c2018-05-22 13:49:31 +0200293 return( ret );
Jerome Forissier5b25c762020-04-07 11:18:49 +0200294 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200295
296 return( 0 );
297}
298
299/*
300 * Set prediction resistance
301 */
302void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
303 int resistance )
304{
305 ctx->prediction_resistance = resistance;
306}
307
308/*
Jerome Forissier5b25c762020-04-07 11:18:49 +0200309 * Set entropy length grabbed for seeding
Jens Wiklander817466c2018-05-22 13:49:31 +0200310 */
311void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
312{
313 ctx->entropy_len = len;
314}
315
316/*
317 * Set reseed interval
318 */
319void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval )
320{
321 ctx->reseed_interval = interval;
322}
323
324/*
325 * HMAC_DRBG random function with optional additional data:
326 * 10.1.2.5 (arabic) + 9.3 (Roman)
327 */
328int mbedtls_hmac_drbg_random_with_add( void *p_rng,
329 unsigned char *output, size_t out_len,
330 const unsigned char *additional, size_t add_len )
331{
332 int ret;
333 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
334 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
335 size_t left = out_len;
336 unsigned char *out = output;
337
338 /* II. Check request length */
339 if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST )
340 return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
341
342 /* III. Check input length */
343 if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
344 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
345
346 /* 1. (aka VII and IX) Check reseed counter and PR */
347 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
348 ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
349 ctx->reseed_counter > ctx->reseed_interval ) )
350 {
351 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
352 return( ret );
353
354 add_len = 0; /* VII.4 */
355 }
356
357 /* 2. Use additional data if any */
358 if( additional != NULL && add_len != 0 )
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100359 {
360 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
361 additional, add_len ) ) != 0 )
362 goto exit;
363 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200364
365 /* 3, 4, 5. Generate bytes */
366 while( left != 0 )
367 {
368 size_t use_len = left > md_len ? md_len : left;
369
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100370 if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
371 goto exit;
372 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
373 ctx->V, md_len ) ) != 0 )
374 goto exit;
375 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
376 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200377
378 memcpy( out, ctx->V, use_len );
379 out += use_len;
380 left -= use_len;
381 }
382
383 /* 6. Update */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100384 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
385 additional, add_len ) ) != 0 )
386 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200387
388 /* 7. Update reseed counter */
389 ctx->reseed_counter++;
390
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100391exit:
Jens Wiklander817466c2018-05-22 13:49:31 +0200392 /* 8. Done */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100393 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200394}
395
396/*
397 * HMAC_DRBG random function
398 */
399int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
400{
401 int ret;
402 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
403
404#if defined(MBEDTLS_THREADING_C)
405 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
406 return( ret );
407#endif
408
409 ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
410
411#if defined(MBEDTLS_THREADING_C)
412 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
413 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
414#endif
415
416 return( ret );
417}
418
419/*
420 * Free an HMAC_DRBG context
421 */
422void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
423{
424 if( ctx == NULL )
425 return;
426
427#if defined(MBEDTLS_THREADING_C)
428 mbedtls_mutex_free( &ctx->mutex );
429#endif
430 mbedtls_md_free( &ctx->md_ctx );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100431 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200432}
433
434#if defined(MBEDTLS_FS_IO)
435int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
436{
437 int ret;
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
455exit:
456 fclose( f );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100457 mbedtls_platform_zeroize( buf, sizeof( buf ) );
458
Jens Wiklander817466c2018-05-22 13:49:31 +0200459 return( ret );
460}
461
462int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
463{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100464 int ret = 0;
465 FILE *f = NULL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200466 size_t n;
467 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100468 unsigned char c;
Jens Wiklander817466c2018-05-22 13:49:31 +0200469
470 if( ( f = fopen( path, "rb" ) ) == NULL )
471 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
472
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100473 n = fread( buf, 1, sizeof( buf ), f );
474 if( fread( &c, 1, 1, f ) != 0 )
Jens Wiklander817466c2018-05-22 13:49:31 +0200475 {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100476 ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
477 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200478 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100479 if( n == 0 || ferror( f ) )
Jens Wiklander817466c2018-05-22 13:49:31 +0200480 {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100481 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
482 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200483 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200484 fclose( f );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100485 f = NULL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200486
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100487 ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n );
Jens Wiklander817466c2018-05-22 13:49:31 +0200488
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100489exit:
490 mbedtls_platform_zeroize( buf, sizeof( buf ) );
491 if( f != NULL )
492 fclose( f );
493 if( ret != 0 )
494 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200495 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 */
504int 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 */
514static 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 };
520static 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 */
530static 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 };
535static 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 */
545static size_t test_offset;
546static 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 */
565int 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 */