blob: 167cdd550ebc0a0686a2d748df50408596115deb [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"
Jerome Forissier11fa71b2020-04-20 17:17:56 +020038#include "mbedtls/error.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020039
40#include <string.h>
41
42#if defined(MBEDTLS_FS_IO)
43#include <stdio.h>
44#endif
45
46#if defined(MBEDTLS_SELF_TEST)
47#if defined(MBEDTLS_PLATFORM_C)
48#include "mbedtls/platform.h"
49#else
50#include <stdio.h>
51#define mbedtls_printf printf
52#endif /* MBEDTLS_SELF_TEST */
53#endif /* MBEDTLS_PLATFORM_C */
54
Jens Wiklander817466c2018-05-22 13:49:31 +020055/*
56 * HMAC_DRBG context initialization
57 */
58void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx )
59{
60 memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) );
61
62#if defined(MBEDTLS_THREADING_C)
63 mbedtls_mutex_init( &ctx->mutex );
64#endif
65}
66
67/*
68 * HMAC_DRBG update, using optional additional data (10.1.2.2)
69 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +010070int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx,
71 const unsigned char *additional,
72 size_t add_len )
Jens Wiklander817466c2018-05-22 13:49:31 +020073{
74 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
75 unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
76 unsigned char sep[1];
77 unsigned char K[MBEDTLS_MD_MAX_SIZE];
Jerome Forissier11fa71b2020-04-20 17:17:56 +020078 int ret = MBEDTLS_ERR_MD_BAD_INPUT_DATA;
Jens Wiklander817466c2018-05-22 13:49:31 +020079
80 for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
81 {
82 /* Step 1 or 4 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +010083 if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
84 goto exit;
85 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
86 ctx->V, md_len ) ) != 0 )
87 goto exit;
88 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
89 sep, 1 ) ) != 0 )
90 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +020091 if( rounds == 2 )
Jens Wiklander3d3b0592019-03-20 15:30:29 +010092 {
93 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
94 additional, add_len ) ) != 0 )
95 goto exit;
96 }
97 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, K ) ) != 0 )
98 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +020099
100 /* Step 2 or 5 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100101 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ) ) != 0 )
102 goto exit;
103 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
104 ctx->V, md_len ) ) != 0 )
105 goto exit;
106 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
107 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200108 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100109
110exit:
111 mbedtls_platform_zeroize( K, sizeof( K ) );
112 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200113}
114
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100115#if !defined(MBEDTLS_DEPRECATED_REMOVED)
116void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
117 const unsigned char *additional,
118 size_t add_len )
119{
120 (void) mbedtls_hmac_drbg_update_ret( ctx, additional, add_len );
121}
122#endif /* MBEDTLS_DEPRECATED_REMOVED */
123
Jens Wiklander817466c2018-05-22 13:49:31 +0200124/*
125 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
126 */
127int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
128 const mbedtls_md_info_t * md_info,
129 const unsigned char *data, size_t data_len )
130{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200131 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200132
133 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
134 return( ret );
135
136 /*
137 * Set initial working state.
138 * Use the V memory location, which is currently all 0, to initialize the
139 * MD context with an all-zero key. Then set V to its initial value.
140 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100141 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V,
142 mbedtls_md_get_size( md_info ) ) ) != 0 )
143 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200144 memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) );
145
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100146 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, data, data_len ) ) != 0 )
147 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200148
149 return( 0 );
150}
151
152/*
Jerome Forissier5b25c762020-04-07 11:18:49 +0200153 * Internal function used both for seeding and reseeding the DRBG.
154 * Comments starting with arabic numbers refer to section 10.1.2.4
155 * of SP800-90A, while roman numbers refer to section 9.2.
Jens Wiklander817466c2018-05-22 13:49:31 +0200156 */
Jerome Forissier5b25c762020-04-07 11:18:49 +0200157static int hmac_drbg_reseed_core( mbedtls_hmac_drbg_context *ctx,
158 const unsigned char *additional, size_t len,
159 int use_nonce )
Jens Wiklander817466c2018-05-22 13:49:31 +0200160{
161 unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
Jerome Forissier5b25c762020-04-07 11:18:49 +0200162 size_t seedlen = 0;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200163 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200164
Jens Wiklander817466c2018-05-22 13:49:31 +0200165 {
Jerome Forissier5b25c762020-04-07 11:18:49 +0200166 size_t total_entropy_len;
167
168 if( use_nonce == 0 )
169 total_entropy_len = ctx->entropy_len;
170 else
171 total_entropy_len = ctx->entropy_len * 3 / 2;
172
173 /* III. Check input length */
174 if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
175 total_entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT )
176 {
177 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
178 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200179 }
180
181 memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
182
183 /* IV. Gather entropy_len bytes of entropy for the seed */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100184 if( ( ret = ctx->f_entropy( ctx->p_entropy,
185 seed, ctx->entropy_len ) ) != 0 )
Jerome Forissier5b25c762020-04-07 11:18:49 +0200186 {
Jens Wiklander817466c2018-05-22 13:49:31 +0200187 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
Jerome Forissier5b25c762020-04-07 11:18:49 +0200188 }
189 seedlen += ctx->entropy_len;
Jens Wiklander817466c2018-05-22 13:49:31 +0200190
Jerome Forissier5b25c762020-04-07 11:18:49 +0200191 /* For initial seeding, allow adding of nonce generated
192 * from the entropy source. See Sect 8.6.7 in SP800-90A. */
193 if( use_nonce )
194 {
195 /* Note: We don't merge the two calls to f_entropy() in order
196 * to avoid requesting too much entropy from f_entropy()
197 * at once. Specifically, if the underlying digest is not
198 * SHA-1, 3 / 2 * entropy_len is at least 36 Bytes, which
199 * is larger than the maximum of 32 Bytes that our own
200 * entropy source implementation can emit in a single
201 * call in configurations disabling SHA-512. */
202 if( ( ret = ctx->f_entropy( ctx->p_entropy,
203 seed + seedlen,
204 ctx->entropy_len / 2 ) ) != 0 )
205 {
206 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
207 }
208
209 seedlen += ctx->entropy_len / 2;
210 }
211
Jens Wiklander817466c2018-05-22 13:49:31 +0200212
213 /* 1. Concatenate entropy and additional data if any */
214 if( additional != NULL && len != 0 )
215 {
216 memcpy( seed + seedlen, additional, len );
217 seedlen += len;
218 }
219
220 /* 2. Update state */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100221 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, seed, seedlen ) ) != 0 )
222 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200223
224 /* 3. Reset reseed_counter */
225 ctx->reseed_counter = 1;
226
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100227exit:
Jens Wiklander817466c2018-05-22 13:49:31 +0200228 /* 4. Done */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100229 mbedtls_platform_zeroize( seed, seedlen );
230 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200231}
232
233/*
Jerome Forissier5b25c762020-04-07 11:18:49 +0200234 * HMAC_DRBG reseeding: 10.1.2.4 + 9.2
235 */
236int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
237 const unsigned char *additional, size_t len )
238{
239 return( hmac_drbg_reseed_core( ctx, additional, len, 0 ) );
240}
241
242/*
Jens Wiklander817466c2018-05-22 13:49:31 +0200243 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
Jerome Forissier5b25c762020-04-07 11:18:49 +0200244 *
245 * The nonce is not passed as a separate parameter but extracted
246 * from the entropy source as suggested in 8.6.7.
Jens Wiklander817466c2018-05-22 13:49:31 +0200247 */
248int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
249 const mbedtls_md_info_t * md_info,
250 int (*f_entropy)(void *, unsigned char *, size_t),
251 void *p_entropy,
252 const unsigned char *custom,
253 size_t len )
254{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200255 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200256 size_t md_size;
Jens Wiklander817466c2018-05-22 13:49:31 +0200257
258 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
259 return( ret );
260
261 md_size = mbedtls_md_get_size( md_info );
262
263 /*
264 * Set initial working state.
265 * Use the V memory location, which is currently all 0, to initialize the
266 * MD context with an all-zero key. Then set V to its initial value.
267 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100268 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ) ) != 0 )
269 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200270 memset( ctx->V, 0x01, md_size );
271
272 ctx->f_entropy = f_entropy;
273 ctx->p_entropy = p_entropy;
274
275 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
276
Jerome Forissier5b25c762020-04-07 11:18:49 +0200277 if( ctx->entropy_len == 0 )
278 {
279 /*
280 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
281 * each hash function, then according to SP800-90A rev1 10.1 table 2,
282 * min_entropy_len (in bits) is security_strength.
283 *
284 * (This also matches the sizes used in the NIST test vectors.)
285 */
286 ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
287 md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
288 32; /* better (256+) -> 256 bits */
289 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200290
Jerome Forissier5b25c762020-04-07 11:18:49 +0200291 if( ( ret = hmac_drbg_reseed_core( ctx, custom, len,
292 1 /* add nonce */ ) ) != 0 )
293 {
Jens Wiklander817466c2018-05-22 13:49:31 +0200294 return( ret );
Jerome Forissier5b25c762020-04-07 11:18:49 +0200295 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200296
297 return( 0 );
298}
299
300/*
301 * Set prediction resistance
302 */
303void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
304 int resistance )
305{
306 ctx->prediction_resistance = resistance;
307}
308
309/*
Jerome Forissier5b25c762020-04-07 11:18:49 +0200310 * Set entropy length grabbed for seeding
Jens Wiklander817466c2018-05-22 13:49:31 +0200311 */
312void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
313{
314 ctx->entropy_len = len;
315}
316
317/*
318 * Set reseed interval
319 */
320void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval )
321{
322 ctx->reseed_interval = interval;
323}
324
325/*
326 * HMAC_DRBG random function with optional additional data:
327 * 10.1.2.5 (arabic) + 9.3 (Roman)
328 */
329int mbedtls_hmac_drbg_random_with_add( void *p_rng,
330 unsigned char *output, size_t out_len,
331 const unsigned char *additional, size_t add_len )
332{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200333 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200334 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
335 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
336 size_t left = out_len;
337 unsigned char *out = output;
338
339 /* II. Check request length */
340 if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST )
341 return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
342
343 /* III. Check input length */
344 if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
345 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
346
347 /* 1. (aka VII and IX) Check reseed counter and PR */
348 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
349 ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
350 ctx->reseed_counter > ctx->reseed_interval ) )
351 {
352 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
353 return( ret );
354
355 add_len = 0; /* VII.4 */
356 }
357
358 /* 2. Use additional data if any */
359 if( additional != NULL && add_len != 0 )
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100360 {
361 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
362 additional, add_len ) ) != 0 )
363 goto exit;
364 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200365
366 /* 3, 4, 5. Generate bytes */
367 while( left != 0 )
368 {
369 size_t use_len = left > md_len ? md_len : left;
370
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100371 if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
372 goto exit;
373 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
374 ctx->V, md_len ) ) != 0 )
375 goto exit;
376 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
377 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200378
379 memcpy( out, ctx->V, use_len );
380 out += use_len;
381 left -= use_len;
382 }
383
384 /* 6. Update */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100385 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
386 additional, add_len ) ) != 0 )
387 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200388
389 /* 7. Update reseed counter */
390 ctx->reseed_counter++;
391
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100392exit:
Jens Wiklander817466c2018-05-22 13:49:31 +0200393 /* 8. Done */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100394 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200395}
396
397/*
398 * HMAC_DRBG random function
399 */
400int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
401{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200402 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200403 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
404
405#if defined(MBEDTLS_THREADING_C)
406 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
407 return( ret );
408#endif
409
410 ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
411
412#if defined(MBEDTLS_THREADING_C)
413 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
414 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
415#endif
416
417 return( ret );
418}
419
420/*
421 * Free an HMAC_DRBG context
422 */
423void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
424{
425 if( ctx == NULL )
426 return;
427
428#if defined(MBEDTLS_THREADING_C)
429 mbedtls_mutex_free( &ctx->mutex );
430#endif
431 mbedtls_md_free( &ctx->md_ctx );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100432 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200433}
434
435#if defined(MBEDTLS_FS_IO)
436int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
437{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200438 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200439 FILE *f;
440 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
441
442 if( ( f = fopen( path, "wb" ) ) == NULL )
443 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
444
445 if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
446 goto exit;
447
448 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
449 {
450 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
451 goto exit;
452 }
453
454 ret = 0;
455
456exit:
457 fclose( f );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100458 mbedtls_platform_zeroize( buf, sizeof( buf ) );
459
Jens Wiklander817466c2018-05-22 13:49:31 +0200460 return( ret );
461}
462
463int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
464{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100465 int ret = 0;
466 FILE *f = NULL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200467 size_t n;
468 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100469 unsigned char c;
Jens Wiklander817466c2018-05-22 13:49:31 +0200470
471 if( ( f = fopen( path, "rb" ) ) == NULL )
472 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
473
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100474 n = fread( buf, 1, sizeof( buf ), f );
475 if( fread( &c, 1, 1, f ) != 0 )
Jens Wiklander817466c2018-05-22 13:49:31 +0200476 {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100477 ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
478 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200479 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100480 if( n == 0 || ferror( f ) )
Jens Wiklander817466c2018-05-22 13:49:31 +0200481 {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100482 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
483 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200484 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200485 fclose( f );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100486 f = NULL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200487
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100488 ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n );
Jens Wiklander817466c2018-05-22 13:49:31 +0200489
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100490exit:
491 mbedtls_platform_zeroize( buf, sizeof( buf ) );
492 if( f != NULL )
493 fclose( f );
494 if( ret != 0 )
495 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200496 return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
497}
498#endif /* MBEDTLS_FS_IO */
499
500
501#if defined(MBEDTLS_SELF_TEST)
502
503#if !defined(MBEDTLS_SHA1_C)
504/* Dummy checkup routine */
505int mbedtls_hmac_drbg_self_test( int verbose )
506{
507 (void) verbose;
508 return( 0 );
509}
510#else
511
512#define OUTPUT_LEN 80
513
514/* From a NIST PR=true test vector */
515static const unsigned char entropy_pr[] = {
516 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
517 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
518 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
519 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
520 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
521static const unsigned char result_pr[OUTPUT_LEN] = {
522 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
523 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
524 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
525 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
526 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
527 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
528 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
529
530/* From a NIST PR=false test vector */
531static const unsigned char entropy_nopr[] = {
532 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
533 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
534 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
535 0xe9, 0x9d, 0xfe, 0xdf };
536static const unsigned char result_nopr[OUTPUT_LEN] = {
537 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
538 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
539 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
540 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
541 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
542 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
543 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
544
545/* "Entropy" from buffer */
546static size_t test_offset;
547static int hmac_drbg_self_test_entropy( void *data,
548 unsigned char *buf, size_t len )
549{
550 const unsigned char *p = data;
551 memcpy( buf, p + test_offset, len );
552 test_offset += len;
553 return( 0 );
554}
555
556#define CHK( c ) if( (c) != 0 ) \
557 { \
558 if( verbose != 0 ) \
559 mbedtls_printf( "failed\n" ); \
560 return( 1 ); \
561 }
562
563/*
564 * Checkup routine for HMAC_DRBG with SHA-1
565 */
566int mbedtls_hmac_drbg_self_test( int verbose )
567{
568 mbedtls_hmac_drbg_context ctx;
569 unsigned char buf[OUTPUT_LEN];
570 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
571
572 mbedtls_hmac_drbg_init( &ctx );
573
574 /*
575 * PR = True
576 */
577 if( verbose != 0 )
578 mbedtls_printf( " HMAC_DRBG (PR = True) : " );
579
580 test_offset = 0;
581 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
582 hmac_drbg_self_test_entropy, (void *) entropy_pr,
583 NULL, 0 ) );
584 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
585 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
586 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
587 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
588 mbedtls_hmac_drbg_free( &ctx );
589
590 mbedtls_hmac_drbg_free( &ctx );
591
592 if( verbose != 0 )
593 mbedtls_printf( "passed\n" );
594
595 /*
596 * PR = False
597 */
598 if( verbose != 0 )
599 mbedtls_printf( " HMAC_DRBG (PR = False) : " );
600
601 mbedtls_hmac_drbg_init( &ctx );
602
603 test_offset = 0;
604 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
605 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
606 NULL, 0 ) );
607 CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
608 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
609 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
610 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
611 mbedtls_hmac_drbg_free( &ctx );
612
613 mbedtls_hmac_drbg_free( &ctx );
614
615 if( verbose != 0 )
616 mbedtls_printf( "passed\n" );
617
618 if( verbose != 0 )
619 mbedtls_printf( "\n" );
620
621 return( 0 );
622}
623#endif /* MBEDTLS_SHA1_C */
624#endif /* MBEDTLS_SELF_TEST */
625
626#endif /* MBEDTLS_HMAC_DRBG_C */