blob: 2ebdac0883bbc9bd0fa1662d6f033e71645d21e2 [file] [log] [blame]
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +01001/*
2 * HMAC_DRBG implementation (NIST SP 800-90)
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * 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.
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010020 */
21
22/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010023 * The NIST SP 800-90A DRBGs are described in the following publication.
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010024 * http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010025 * References below are based on rev. 1 (January 2012).
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010026 */
27
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020028#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000029#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020030#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020031#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020032#endif
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010033
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020034#if defined(MBEDTLS_HMAC_DRBG_C)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010035
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000036#include "mbedtls/hmac_drbg.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050037#include "mbedtls/platform_util.h"
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010038
Rich Evans00ab4702015-02-06 13:43:58 +000039#include <string.h>
40
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#if defined(MBEDTLS_FS_IO)
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +010042#include <stdio.h>
43#endif
44
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020045#if defined(MBEDTLS_SELF_TEST)
46#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000047#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010048#else
Rich Evans00ab4702015-02-06 13:43:58 +000049#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020050#define mbedtls_printf printf
51#endif /* MBEDTLS_SELF_TEST */
52#endif /* MBEDTLS_PLATFORM_C */
Paul Bakker7dc4c442014-02-01 22:50:26 +010053
Arto Kinnunen5b366932019-11-20 16:13:13 +020054#define HMAC_NONCE_YES 0x4AAAAAAA
55#define HMAC_NONCE_NO 0x75555555
56
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010057/*
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +020058 * HMAC_DRBG context initialization
59 */
60void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx )
61{
62 memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010063
64#if defined(MBEDTLS_THREADING_C)
65 mbedtls_mutex_init( &ctx->mutex );
66#endif
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +020067}
68
69/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010070 * HMAC_DRBG update, using optional additional data (10.1.2.2)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010071 */
Gilles Peskinee0e9c572018-09-11 16:47:16 +020072int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx,
73 const unsigned char *additional,
74 size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010075{
Hanno Beckerd3827c72019-09-03 12:56:37 +010076 size_t md_len = mbedtls_md_get_size(
77 mbedtls_md_get_handle( &ctx->md_ctx ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010078 unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
79 unsigned char sep[1];
Arto Kinnunen5b366932019-11-20 16:13:13 +020080 volatile unsigned char flow_counter = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020081 unsigned char K[MBEDTLS_MD_MAX_SIZE];
Arto Kinnunen5b366932019-11-20 16:13:13 +020082 int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010083
84 for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
85 {
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010086 /* Step 1 or 4 */
Arto Kinnunen5b366932019-11-20 16:13:13 +020087 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +020088 if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
89 goto exit;
Arto Kinnunen5b366932019-11-20 16:13:13 +020090
91 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +020092 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
93 ctx->V, md_len ) ) != 0 )
94 goto exit;
Arto Kinnunen5b366932019-11-20 16:13:13 +020095
96 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +020097 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
98 sep, 1 ) ) != 0 )
99 goto exit;
Arto Kinnunen5b366932019-11-20 16:13:13 +0200100
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100101 if( rounds == 2 )
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200102 {
Arto Kinnunen5b366932019-11-20 16:13:13 +0200103 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200104 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
105 additional, add_len ) ) != 0 )
106 goto exit;
107 }
Arto Kinnunen5b366932019-11-20 16:13:13 +0200108
109 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200110 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, K ) ) != 0 )
111 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100112
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100113 /* Step 2 or 5 */
Arto Kinnunen5b366932019-11-20 16:13:13 +0200114 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200115 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ) ) != 0 )
116 goto exit;
Arto Kinnunen5b366932019-11-20 16:13:13 +0200117
118 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200119 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
120 ctx->V, md_len ) ) != 0 )
121 goto exit;
Arto Kinnunen5b366932019-11-20 16:13:13 +0200122
123 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200124 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
125 goto exit;
Arto Kinnunen5299a422019-11-25 16:19:25 +0200126 flow_counter++;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100127 }
Gilles Peskineafa80372018-09-11 15:35:41 +0200128
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200129exit:
Arto Kinnunen5b366932019-11-20 16:13:13 +0200130
Arto Kinnunen5299a422019-11-25 16:19:25 +0200131 mbedtls_platform_zeroize( K, sizeof( K ) );
132 /* Check for possible attack.
133 * Counters needs to have correct values when returning success
134 */
135 if ( ret != 0 )
136 return( ret ); // error case, return immediately
137
138 if ( ( ( flow_counter == 8 ) && ( sep[0] == 1 ) ) ||
139 ( ( flow_counter == 18 ) && ( sep[0] == 2 ) ) )
Arto Kinnunen5b366932019-11-20 16:13:13 +0200140 {
Arto Kinnunen5299a422019-11-25 16:19:25 +0200141 flow_counter = flow_counter - sep[0];
142 // Double check flow_counter
143 if ( ( flow_counter == 7 ) || ( flow_counter == 16 ) )
Arto Kinnunen5b366932019-11-20 16:13:13 +0200144 {
Arto Kinnunen5299a422019-11-25 16:19:25 +0200145 return ret; // success, return 0 from ret
Arto Kinnunen5b366932019-11-20 16:13:13 +0200146 }
147 }
148
Arto Kinnunen5299a422019-11-25 16:19:25 +0200149 return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100150}
151
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200152#if !defined(MBEDTLS_DEPRECATED_REMOVED)
153void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
154 const unsigned char *additional,
155 size_t add_len )
156{
157 (void) mbedtls_hmac_drbg_update_ret( ctx, additional, add_len );
158}
159#endif /* MBEDTLS_DEPRECATED_REMOVED */
160
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100161/*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100162 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100163 */
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200164int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
Arto Kinnunen5b366932019-11-20 16:13:13 +0200165 mbedtls_md_handle_t md_info,
166 const unsigned char *data, size_t data_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100167{
Arto Kinnunen5b366932019-11-20 16:13:13 +0200168 int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100169
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200170 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100171 return( ret );
172
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100173 /*
174 * Set initial working state.
175 * Use the V memory location, which is currently all 0, to initialize the
176 * MD context with an all-zero key. Then set V to its initial value.
177 */
Gilles Peskineb7f71c82018-09-11 16:54:57 +0200178 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V,
179 mbedtls_md_get_size( md_info ) ) ) != 0 )
180 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200181 memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100182
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200183 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, data, data_len ) ) != 0 )
184 return( ret );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100185
Arto Kinnunen5b366932019-11-20 16:13:13 +0200186 return( ret );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100187}
188
Hanno Becker31c95e12019-08-27 09:22:09 +0100189/*
190 * Internal function used both for seeding and reseeding the DRBG.
191 * Comments starting with arabic numbers refer to section 10.1.2.4
192 * of SP800-90A, while roman numbers refer to section 9.2.
193 */
Hanno Beckerb3a06e62019-08-27 09:21:44 +0100194static int hmac_drbg_reseed_core( mbedtls_hmac_drbg_context *ctx,
195 const unsigned char *additional, size_t len,
196 int use_nonce )
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100197{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200198 unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
Hanno Beckereab304c2019-08-26 15:29:14 +0100199 size_t seedlen = 0;
Arto Kinnunen5b366932019-11-20 16:13:13 +0200200 size_t total_entropy_len;
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200201 int ret;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100202
Arto Kinnunen5b366932019-11-20 16:13:13 +0200203 if( use_nonce == HMAC_NONCE_NO )
204 total_entropy_len = ctx->entropy_len;
205 else
206 total_entropy_len = ctx->entropy_len * 3 / 2;
207
208 /* III. Check input length */
209 if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
210 total_entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100211 {
Arto Kinnunen5b366932019-11-20 16:13:13 +0200212 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100213 }
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100214
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200215 memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100216
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100217 /* IV. Gather entropy_len bytes of entropy for the seed */
Gilles Peskineb7f71c82018-09-11 16:54:57 +0200218 if( ( ret = ctx->f_entropy( ctx->p_entropy,
219 seed, ctx->entropy_len ) ) != 0 )
Hanno Beckereab304c2019-08-26 15:29:14 +0100220 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200221 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
Hanno Beckereab304c2019-08-26 15:29:14 +0100222 }
223 seedlen += ctx->entropy_len;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100224
Hanno Becker31c95e12019-08-27 09:22:09 +0100225 /* For initial seeding, allow adding of nonce generated
226 * from the entropy source. See Sect 8.6.7 in SP800-90A. */
Arto Kinnunen5b366932019-11-20 16:13:13 +0200227 if( use_nonce == HMAC_NONCE_YES )
Hanno Beckereab304c2019-08-26 15:29:14 +0100228 {
229 /* Note: We don't merge the two calls to f_entropy() in order
230 * to avoid requesting too much entropy from f_entropy()
231 * at once. Specifically, if the underlying digest is not
232 * SHA-1, 3 / 2 * entropy_len is at least 36 Bytes, which
233 * is larger than the maximum of 32 Bytes that our own
234 * entropy source implementation can emit in a single
235 * call in configurations disabling SHA-512. */
236 if( ( ret = ctx->f_entropy( ctx->p_entropy,
237 seed + seedlen,
238 ctx->entropy_len / 2 ) ) != 0 )
239 {
240 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
241 }
242
243 seedlen += ctx->entropy_len / 2;
244 }
245
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100246
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100247 /* 1. Concatenate entropy and additional data if any */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100248 if( additional != NULL && len != 0 )
249 {
Teppo Järvelin91d79382019-10-02 09:09:31 +0300250 mbedtls_platform_memcpy( seed + seedlen, additional, len );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100251 seedlen += len;
252 }
253
254 /* 2. Update state */
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200255 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, seed, seedlen ) ) != 0 )
256 goto exit;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100257
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100258 /* 3. Reset reseed_counter */
259 ctx->reseed_counter = 1;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100260
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200261exit:
Arto Kinnunen5299a422019-11-25 16:19:25 +0200262
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100263 /* 4. Done */
Gilles Peskineafa80372018-09-11 15:35:41 +0200264 mbedtls_platform_zeroize( seed, seedlen );
Arto Kinnunen5299a422019-11-25 16:19:25 +0200265
266 if ( ret != 0 )
267 return ret;
268
269 if ( ret == 0 && ctx->reseed_counter == 1 )
270 {
271 /* All ok, return 0 from ret */
272 return ret;
273 }
274
275 return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100276}
277
278/*
Hanno Becker31c95e12019-08-27 09:22:09 +0100279 * HMAC_DRBG reseeding: 10.1.2.4 + 9.2
Hanno Beckereab304c2019-08-26 15:29:14 +0100280 */
281int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
282 const unsigned char *additional, size_t len )
283{
Arto Kinnunen5b366932019-11-20 16:13:13 +0200284 return( hmac_drbg_reseed_core( ctx, additional, len, HMAC_NONCE_NO ) );
Hanno Beckereab304c2019-08-26 15:29:14 +0100285}
286
287/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100288 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
Hanno Becker31c95e12019-08-27 09:22:09 +0100289 *
290 * The nonce is not passed as a separate parameter but extracted
291 * from the entropy source as suggested in 8.6.7.
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100292 */
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200293int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
Hanno Beckera5cedbc2019-07-17 11:21:02 +0100294 mbedtls_md_handle_t md_info,
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100295 int (*f_entropy)(void *, unsigned char *, size_t),
296 void *p_entropy,
297 const unsigned char *custom,
298 size_t len )
299{
300 int ret;
Hanno Beckereab304c2019-08-26 15:29:14 +0100301 size_t md_size;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100302
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200303 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100304 return( ret );
305
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200306 md_size = mbedtls_md_get_size( md_info );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100307
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100308 /*
309 * Set initial working state.
310 * Use the V memory location, which is currently all 0, to initialize the
311 * MD context with an all-zero key. Then set V to its initial value.
312 */
Gilles Peskineb7f71c82018-09-11 16:54:57 +0200313 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ) ) != 0 )
314 return( ret );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100315 memset( ctx->V, 0x01, md_size );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100316
317 ctx->f_entropy = f_entropy;
318 ctx->p_entropy = p_entropy;
319
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200320 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100321
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100322 /*
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100323 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
324 * each hash function, then according to SP800-90A rev1 10.1 table 2,
325 * min_entropy_len (in bits) is security_strength.
326 *
327 * (This also matches the sizes used in the NIST test vectors.)
328 */
Hanno Beckereab304c2019-08-26 15:29:14 +0100329 ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
330 md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
331 32; /* better (256+) -> 256 bits */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100332
Arto Kinnunen5b366932019-11-20 16:13:13 +0200333 if( ( ret = hmac_drbg_reseed_core( ctx, custom, len, HMAC_NONCE_YES ) ) != 0 )
Hanno Beckereab304c2019-08-26 15:29:14 +0100334 {
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100335 return( ret );
Hanno Beckereab304c2019-08-26 15:29:14 +0100336 }
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100337
Arto Kinnunen5b366932019-11-20 16:13:13 +0200338 return( ret );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100339}
340
341/*
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100342 * Set prediction resistance
343 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200344void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100345 int resistance )
346{
347 ctx->prediction_resistance = resistance;
348}
349
350/*
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100351 * Set entropy length grabbed for reseeds
352 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200353void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100354{
355 ctx->entropy_len = len;
356}
357
358/*
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100359 * Set reseed interval
360 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200361void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval )
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100362{
363 ctx->reseed_interval = interval;
364}
365
366/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100367 * HMAC_DRBG random function with optional additional data:
368 * 10.1.2.5 (arabic) + 9.3 (Roman)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100369 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200370int mbedtls_hmac_drbg_random_with_add( void *p_rng,
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100371 unsigned char *output, size_t out_len,
372 const unsigned char *additional, size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100373{
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100374 int ret;
Arto Kinnunen5b366932019-11-20 16:13:13 +0200375 volatile unsigned char *output_fi = output;
376 volatile size_t out_len_fi = out_len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200377 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
Hanno Beckerd3827c72019-09-03 12:56:37 +0100378 size_t md_len = mbedtls_md_get_size(
379 mbedtls_md_get_handle( &ctx->md_ctx ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100380 size_t left = out_len;
381 unsigned char *out = output;
382
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100383 /* II. Check request length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200384 if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST )
385 return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100386
387 /* III. Check input length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200388 if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
389 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100390
391 /* 1. (aka VII and IX) Check reseed counter and PR */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100392 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200393 ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100394 ctx->reseed_counter > ctx->reseed_interval ) )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100395 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200396 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100397 return( ret );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100398
399 add_len = 0; /* VII.4 */
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100400 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100401
402 /* 2. Use additional data if any */
403 if( additional != NULL && add_len != 0 )
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200404 {
405 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
406 additional, add_len ) ) != 0 )
407 goto exit;
408 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100409
410 /* 3, 4, 5. Generate bytes */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100411 while( left != 0 )
412 {
413 size_t use_len = left > md_len ? md_len : left;
414
Gilles Peskineb7f71c82018-09-11 16:54:57 +0200415 if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
416 goto exit;
417 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
418 ctx->V, md_len ) ) != 0 )
419 goto exit;
420 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
421 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100422
Teppo Järvelin91d79382019-10-02 09:09:31 +0300423 mbedtls_platform_memcpy( out, ctx->V, use_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100424 out += use_len;
425 left -= use_len;
426 }
427
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100428 /* 6. Update */
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200429 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
430 additional, add_len ) ) != 0 )
431 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100432
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100433 /* 7. Update reseed counter */
434 ctx->reseed_counter++;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100435
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200436exit:
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100437 /* 8. Done */
Arto Kinnunen5b366932019-11-20 16:13:13 +0200438
Arto Kinnunen5299a422019-11-25 16:19:25 +0200439 if ( ret != 0 )
440 return ret;
441
442 /*
443 * Check doubled variables and illegal conditions in case of possible
444 * attack.
445 */
446 if ( ( out_len_fi == out_len ) && ( output_fi == output) &&
447 ( left == 0 ) )
Arto Kinnunen5b366932019-11-20 16:13:13 +0200448 {
Arto Kinnunen5299a422019-11-25 16:19:25 +0200449 return ret; // Success, return 0
Arto Kinnunen5b366932019-11-20 16:13:13 +0200450 }
451
Arto Kinnunen5299a422019-11-25 16:19:25 +0200452 return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100453}
454
455/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100456 * HMAC_DRBG random function
457 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200458int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100459{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100460 int ret;
461 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
462
463#if defined(MBEDTLS_THREADING_C)
464 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
465 return( ret );
466#endif
467
468 ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
469
470#if defined(MBEDTLS_THREADING_C)
471 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
472 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
473#endif
474
475 return( ret );
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100476}
477
478/*
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100479 * Free an HMAC_DRBG context
480 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100482{
483 if( ctx == NULL )
484 return;
485
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100486#if defined(MBEDTLS_THREADING_C)
487 mbedtls_mutex_free( &ctx->mutex );
488#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200489 mbedtls_md_free( &ctx->md_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500490 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100491}
492
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200493#if defined(MBEDTLS_FS_IO)
494int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100495{
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100496 int ret;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100497 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200498 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100499
500 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200501 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100502
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200503 if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100504 goto exit;
505
506 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
507 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200508 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
Paul Bakker4c284c92014-03-26 15:33:05 +0100509 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100510 }
511
512 ret = 0;
513
514exit:
515 fclose( f );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500516 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100517
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100518 return( ret );
519}
520
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200521int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100522{
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100523 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200524 FILE *f = NULL;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100525 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200526 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200527 unsigned char c;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100528
529 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200530 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100531
Gilles Peskine82204662018-09-11 18:43:09 +0200532 n = fread( buf, 1, sizeof( buf ), f );
533 if( fread( &c, 1, 1, f ) != 0 )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100534 {
Gilles Peskine82204662018-09-11 18:43:09 +0200535 ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
536 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100537 }
Gilles Peskine82204662018-09-11 18:43:09 +0200538 if( n == 0 || ferror( f ) )
539 {
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100540 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200541 goto exit;
542 }
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100543 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200544 f = NULL;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100545
Gilles Peskine82204662018-09-11 18:43:09 +0200546 ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n );
547
548exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500549 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200550 if( f != NULL )
551 fclose( f );
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100552 if( ret != 0 )
553 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200554 return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100555}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200556#endif /* MBEDTLS_FS_IO */
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100557
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100558
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200559#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100560
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200561#if !defined(MBEDTLS_SHA1_C)
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100562/* Dummy checkup routine */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200563int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100564{
Manuel Pégourié-Gonnardd1004f02015-08-07 10:46:54 +0200565 (void) verbose;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100566 return( 0 );
567}
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100568#else
569
570#define OUTPUT_LEN 80
571
572/* From a NIST PR=true test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000573static const unsigned char entropy_pr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100574 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
575 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
576 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
577 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
578 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
579static const unsigned char result_pr[OUTPUT_LEN] = {
580 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
581 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
582 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
583 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
584 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
585 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
586 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
587
588/* From a NIST PR=false test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000589static const unsigned char entropy_nopr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100590 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
591 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
592 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
593 0xe9, 0x9d, 0xfe, 0xdf };
594static const unsigned char result_nopr[OUTPUT_LEN] = {
595 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
596 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
597 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
598 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
599 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
600 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
601 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
602
603/* "Entropy" from buffer */
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100604static size_t test_offset;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100605static int hmac_drbg_self_test_entropy( void *data,
606 unsigned char *buf, size_t len )
607{
608 const unsigned char *p = data;
Teppo Järvelinb5c46712019-10-04 13:35:55 +0300609 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100610 test_offset += len;
611 return( 0 );
612}
613
Paul Bakker7dc4c442014-02-01 22:50:26 +0100614#define CHK( c ) if( (c) != 0 ) \
615 { \
616 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200617 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100618 return( 1 ); \
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100619 }
620
621/*
622 * Checkup routine for HMAC_DRBG with SHA-1
623 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200624int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100625{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200626 mbedtls_hmac_drbg_context ctx;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100627 unsigned char buf[OUTPUT_LEN];
Hanno Beckera5cedbc2019-07-17 11:21:02 +0100628 mbedtls_md_handle_t md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100629
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200630 mbedtls_hmac_drbg_init( &ctx );
631
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100632 /*
633 * PR = True
634 */
635 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200636 mbedtls_printf( " HMAC_DRBG (PR = True) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100637
638 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200639 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000640 hmac_drbg_self_test_entropy, (void *) entropy_pr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100641 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200642 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
643 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
644 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100645 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200646 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100647
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100648 mbedtls_hmac_drbg_free( &ctx );
649
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100650 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200651 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100652
653 /*
654 * PR = False
655 */
656 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200657 mbedtls_printf( " HMAC_DRBG (PR = False) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100658
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100659 mbedtls_hmac_drbg_init( &ctx );
660
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100661 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200662 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000663 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100664 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200665 CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
666 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
667 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100668 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200669 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100670
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100671 mbedtls_hmac_drbg_free( &ctx );
672
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100673 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200674 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100675
676 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200677 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100678
679 return( 0 );
680}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200681#endif /* MBEDTLS_SHA1_C */
682#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100683
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200684#endif /* MBEDTLS_HMAC_DRBG_C */