blob: de9706885cab908606dbd0702ea075bba5bbf7a1 [file] [log] [blame]
Jens Wiklander817466c2018-05-22 13:49:31 +02001/*
2 * HMAC_DRBG implementation (NIST SP 800-90)
3 *
Jerome Forissier79013242021-07-28 10:24:04 +02004 * Copyright The Mbed TLS Contributors
5 * SPDX-License-Identifier: Apache-2.0
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.
Jens Wiklander817466c2018-05-22 13:49:31 +020018 */
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
Jerome Forissier79013242021-07-28 10:24:04 +020026#include "common.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020027
28#if defined(MBEDTLS_HMAC_DRBG_C)
29
30#include "mbedtls/hmac_drbg.h"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010031#include "mbedtls/platform_util.h"
Jerome Forissier11fa71b2020-04-20 17:17:56 +020032#include "mbedtls/error.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020033
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
Jens Wiklander817466c2018-05-22 13:49:31 +020049/*
50 * HMAC_DRBG context initialization
51 */
52void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx )
53{
54 memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) );
55
Jerome Forissier79013242021-07-28 10:24:04 +020056 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
Jens Wiklander817466c2018-05-22 13:49:31 +020057}
58
59/*
60 * HMAC_DRBG update, using optional additional data (10.1.2.2)
61 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +010062int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx,
63 const unsigned char *additional,
64 size_t add_len )
Jens Wiklander817466c2018-05-22 13:49:31 +020065{
66 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
67 unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
68 unsigned char sep[1];
69 unsigned char K[MBEDTLS_MD_MAX_SIZE];
Jerome Forissier11fa71b2020-04-20 17:17:56 +020070 int ret = MBEDTLS_ERR_MD_BAD_INPUT_DATA;
Jens Wiklander817466c2018-05-22 13:49:31 +020071
72 for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
73 {
74 /* Step 1 or 4 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +010075 if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
76 goto exit;
77 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
78 ctx->V, md_len ) ) != 0 )
79 goto exit;
80 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
81 sep, 1 ) ) != 0 )
82 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +020083 if( rounds == 2 )
Jens Wiklander3d3b0592019-03-20 15:30:29 +010084 {
85 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
86 additional, add_len ) ) != 0 )
87 goto exit;
88 }
89 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, K ) ) != 0 )
90 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +020091
92 /* Step 2 or 5 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +010093 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ) ) != 0 )
94 goto exit;
95 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
96 ctx->V, md_len ) ) != 0 )
97 goto exit;
98 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
99 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200100 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100101
102exit:
103 mbedtls_platform_zeroize( K, sizeof( K ) );
104 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200105}
106
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100107#if !defined(MBEDTLS_DEPRECATED_REMOVED)
108void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
109 const unsigned char *additional,
110 size_t add_len )
111{
112 (void) mbedtls_hmac_drbg_update_ret( ctx, additional, add_len );
113}
114#endif /* MBEDTLS_DEPRECATED_REMOVED */
115
Jens Wiklander817466c2018-05-22 13:49:31 +0200116/*
117 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
118 */
119int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
120 const mbedtls_md_info_t * md_info,
121 const unsigned char *data, size_t data_len )
122{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200123 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200124
125 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
126 return( ret );
127
Jerome Forissier79013242021-07-28 10:24:04 +0200128#if defined(MBEDTLS_THREADING_C)
129 mbedtls_mutex_init( &ctx->mutex );
130#endif
131
Jens Wiklander817466c2018-05-22 13:49:31 +0200132 /*
133 * Set initial working state.
134 * Use the V memory location, which is currently all 0, to initialize the
135 * MD context with an all-zero key. Then set V to its initial value.
136 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100137 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V,
138 mbedtls_md_get_size( md_info ) ) ) != 0 )
139 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200140 memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) );
141
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100142 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, data, data_len ) ) != 0 )
143 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200144
145 return( 0 );
146}
147
148/*
Jerome Forissier5b25c762020-04-07 11:18:49 +0200149 * Internal function used both for seeding and reseeding the DRBG.
150 * Comments starting with arabic numbers refer to section 10.1.2.4
151 * of SP800-90A, while roman numbers refer to section 9.2.
Jens Wiklander817466c2018-05-22 13:49:31 +0200152 */
Jerome Forissier5b25c762020-04-07 11:18:49 +0200153static int hmac_drbg_reseed_core( mbedtls_hmac_drbg_context *ctx,
154 const unsigned char *additional, size_t len,
155 int use_nonce )
Jens Wiklander817466c2018-05-22 13:49:31 +0200156{
157 unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
Jerome Forissier5b25c762020-04-07 11:18:49 +0200158 size_t seedlen = 0;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200159 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200160
Jens Wiklander817466c2018-05-22 13:49:31 +0200161 {
Jerome Forissier5b25c762020-04-07 11:18:49 +0200162 size_t total_entropy_len;
163
164 if( use_nonce == 0 )
165 total_entropy_len = ctx->entropy_len;
166 else
167 total_entropy_len = ctx->entropy_len * 3 / 2;
168
169 /* III. Check input length */
170 if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
171 total_entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT )
172 {
173 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
174 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200175 }
176
177 memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
178
179 /* IV. Gather entropy_len bytes of entropy for the seed */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100180 if( ( ret = ctx->f_entropy( ctx->p_entropy,
181 seed, ctx->entropy_len ) ) != 0 )
Jerome Forissier5b25c762020-04-07 11:18:49 +0200182 {
Jens Wiklander817466c2018-05-22 13:49:31 +0200183 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
Jerome Forissier5b25c762020-04-07 11:18:49 +0200184 }
185 seedlen += ctx->entropy_len;
Jens Wiklander817466c2018-05-22 13:49:31 +0200186
Jerome Forissier5b25c762020-04-07 11:18:49 +0200187 /* For initial seeding, allow adding of nonce generated
188 * from the entropy source. See Sect 8.6.7 in SP800-90A. */
189 if( use_nonce )
190 {
191 /* Note: We don't merge the two calls to f_entropy() in order
192 * to avoid requesting too much entropy from f_entropy()
193 * at once. Specifically, if the underlying digest is not
194 * SHA-1, 3 / 2 * entropy_len is at least 36 Bytes, which
195 * is larger than the maximum of 32 Bytes that our own
196 * entropy source implementation can emit in a single
197 * call in configurations disabling SHA-512. */
198 if( ( ret = ctx->f_entropy( ctx->p_entropy,
199 seed + seedlen,
200 ctx->entropy_len / 2 ) ) != 0 )
201 {
202 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
203 }
204
205 seedlen += ctx->entropy_len / 2;
206 }
207
Jens Wiklander817466c2018-05-22 13:49:31 +0200208
209 /* 1. Concatenate entropy and additional data if any */
210 if( additional != NULL && len != 0 )
211 {
212 memcpy( seed + seedlen, additional, len );
213 seedlen += len;
214 }
215
216 /* 2. Update state */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100217 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, seed, seedlen ) ) != 0 )
218 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200219
220 /* 3. Reset reseed_counter */
221 ctx->reseed_counter = 1;
222
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100223exit:
Jens Wiklander817466c2018-05-22 13:49:31 +0200224 /* 4. Done */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100225 mbedtls_platform_zeroize( seed, seedlen );
226 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200227}
228
229/*
Jerome Forissier5b25c762020-04-07 11:18:49 +0200230 * HMAC_DRBG reseeding: 10.1.2.4 + 9.2
231 */
232int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
233 const unsigned char *additional, size_t len )
234{
235 return( hmac_drbg_reseed_core( ctx, additional, len, 0 ) );
236}
237
238/*
Jens Wiklander817466c2018-05-22 13:49:31 +0200239 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
Jerome Forissier5b25c762020-04-07 11:18:49 +0200240 *
241 * The nonce is not passed as a separate parameter but extracted
242 * from the entropy source as suggested in 8.6.7.
Jens Wiklander817466c2018-05-22 13:49:31 +0200243 */
244int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
245 const mbedtls_md_info_t * md_info,
246 int (*f_entropy)(void *, unsigned char *, size_t),
247 void *p_entropy,
248 const unsigned char *custom,
249 size_t len )
250{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200251 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200252 size_t md_size;
Jens Wiklander817466c2018-05-22 13:49:31 +0200253
254 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
255 return( ret );
256
Jerome Forissier79013242021-07-28 10:24:04 +0200257 /* The mutex is initialized iff the md context is set up. */
258#if defined(MBEDTLS_THREADING_C)
259 mbedtls_mutex_init( &ctx->mutex );
260#endif
261
Jens Wiklander817466c2018-05-22 13:49:31 +0200262 md_size = mbedtls_md_get_size( md_info );
263
264 /*
265 * Set initial working state.
266 * Use the V memory location, which is currently all 0, to initialize the
267 * MD context with an all-zero key. Then set V to its initial value.
268 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100269 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ) ) != 0 )
270 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200271 memset( ctx->V, 0x01, md_size );
272
273 ctx->f_entropy = f_entropy;
274 ctx->p_entropy = p_entropy;
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{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200332 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200333 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{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200401 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200402 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/*
Jerome Forissier79013242021-07-28 10:24:04 +0200420 * This function resets HMAC_DRBG context to the state immediately
421 * after initial call of mbedtls_hmac_drbg_init().
Jens Wiklander817466c2018-05-22 13:49:31 +0200422 */
423void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
424{
425 if( ctx == NULL )
426 return;
427
428#if defined(MBEDTLS_THREADING_C)
Jerome Forissier79013242021-07-28 10:24:04 +0200429 /* The mutex is initialized iff the md context is set up. */
430 if( ctx->md_ctx.md_info != NULL )
431 mbedtls_mutex_free( &ctx->mutex );
Jens Wiklander817466c2018-05-22 13:49:31 +0200432#endif
433 mbedtls_md_free( &ctx->md_ctx );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100434 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
Jerome Forissier79013242021-07-28 10:24:04 +0200435 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200436}
437
438#if defined(MBEDTLS_FS_IO)
439int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
440{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200441 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200442 FILE *f;
443 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
444
445 if( ( f = fopen( path, "wb" ) ) == NULL )
446 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
447
448 if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
449 goto exit;
450
451 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
452 {
453 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
454 goto exit;
455 }
456
457 ret = 0;
458
459exit:
460 fclose( f );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100461 mbedtls_platform_zeroize( buf, sizeof( buf ) );
462
Jens Wiklander817466c2018-05-22 13:49:31 +0200463 return( ret );
464}
465
466int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
467{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100468 int ret = 0;
469 FILE *f = NULL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200470 size_t n;
471 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100472 unsigned char c;
Jens Wiklander817466c2018-05-22 13:49:31 +0200473
474 if( ( f = fopen( path, "rb" ) ) == NULL )
475 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
476
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100477 n = fread( buf, 1, sizeof( buf ), f );
478 if( fread( &c, 1, 1, f ) != 0 )
Jens Wiklander817466c2018-05-22 13:49:31 +0200479 {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100480 ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
481 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200482 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100483 if( n == 0 || ferror( f ) )
Jens Wiklander817466c2018-05-22 13:49:31 +0200484 {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100485 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
486 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200487 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200488 fclose( f );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100489 f = NULL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200490
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100491 ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n );
Jens Wiklander817466c2018-05-22 13:49:31 +0200492
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100493exit:
494 mbedtls_platform_zeroize( buf, sizeof( buf ) );
495 if( f != NULL )
496 fclose( f );
497 if( ret != 0 )
498 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200499 return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
500}
501#endif /* MBEDTLS_FS_IO */
502
503
504#if defined(MBEDTLS_SELF_TEST)
505
506#if !defined(MBEDTLS_SHA1_C)
507/* Dummy checkup routine */
508int mbedtls_hmac_drbg_self_test( int verbose )
509{
510 (void) verbose;
511 return( 0 );
512}
513#else
514
515#define OUTPUT_LEN 80
516
517/* From a NIST PR=true test vector */
518static const unsigned char entropy_pr[] = {
519 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
520 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
521 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
522 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
523 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
524static const unsigned char result_pr[OUTPUT_LEN] = {
525 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
526 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
527 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
528 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
529 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
530 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
531 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
532
533/* From a NIST PR=false test vector */
534static const unsigned char entropy_nopr[] = {
535 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
536 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
537 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
538 0xe9, 0x9d, 0xfe, 0xdf };
539static const unsigned char result_nopr[OUTPUT_LEN] = {
540 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
541 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
542 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
543 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
544 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
545 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
546 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
547
548/* "Entropy" from buffer */
549static size_t test_offset;
550static int hmac_drbg_self_test_entropy( void *data,
551 unsigned char *buf, size_t len )
552{
553 const unsigned char *p = data;
554 memcpy( buf, p + test_offset, len );
555 test_offset += len;
556 return( 0 );
557}
558
559#define CHK( c ) if( (c) != 0 ) \
560 { \
561 if( verbose != 0 ) \
562 mbedtls_printf( "failed\n" ); \
563 return( 1 ); \
564 }
565
566/*
567 * Checkup routine for HMAC_DRBG with SHA-1
568 */
569int mbedtls_hmac_drbg_self_test( int verbose )
570{
571 mbedtls_hmac_drbg_context ctx;
572 unsigned char buf[OUTPUT_LEN];
573 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
574
575 mbedtls_hmac_drbg_init( &ctx );
576
577 /*
578 * PR = True
579 */
580 if( verbose != 0 )
581 mbedtls_printf( " HMAC_DRBG (PR = True) : " );
582
583 test_offset = 0;
584 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
585 hmac_drbg_self_test_entropy, (void *) entropy_pr,
586 NULL, 0 ) );
587 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
588 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
589 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
590 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
591 mbedtls_hmac_drbg_free( &ctx );
592
593 mbedtls_hmac_drbg_free( &ctx );
594
595 if( verbose != 0 )
596 mbedtls_printf( "passed\n" );
597
598 /*
599 * PR = False
600 */
601 if( verbose != 0 )
602 mbedtls_printf( " HMAC_DRBG (PR = False) : " );
603
604 mbedtls_hmac_drbg_init( &ctx );
605
606 test_offset = 0;
607 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
608 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
609 NULL, 0 ) );
610 CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
611 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
612 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
613 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
614 mbedtls_hmac_drbg_free( &ctx );
615
616 mbedtls_hmac_drbg_free( &ctx );
617
618 if( verbose != 0 )
619 mbedtls_printf( "passed\n" );
620
621 if( verbose != 0 )
622 mbedtls_printf( "\n" );
623
624 return( 0 );
625}
626#endif /* MBEDTLS_SHA1_C */
627#endif /* MBEDTLS_SELF_TEST */
628
629#endif /* MBEDTLS_HMAC_DRBG_C */