blob: 2b79ee54115783a20d5e463d42ccd1c3e692199f [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"
Arto Kinnunenc5bbdd42019-11-25 17:32:28 +020037#include "mbedtls/platform.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050038#include "mbedtls/platform_util.h"
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010039
Rich Evans00ab4702015-02-06 13:43:58 +000040#include <string.h>
41
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020042#if defined(MBEDTLS_FS_IO)
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +010043#include <stdio.h>
44#endif
45
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020046#if defined(MBEDTLS_SELF_TEST)
47#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000048#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010049#else
Rich Evans00ab4702015-02-06 13:43:58 +000050#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020051#define mbedtls_printf printf
52#endif /* MBEDTLS_SELF_TEST */
53#endif /* MBEDTLS_PLATFORM_C */
Paul Bakker7dc4c442014-02-01 22:50:26 +010054
Arto Kinnunen5b366932019-11-20 16:13:13 +020055#define HMAC_NONCE_YES 0x4AAAAAAA
56#define HMAC_NONCE_NO 0x75555555
57
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010058/*
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +020059 * HMAC_DRBG context initialization
60 */
61void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx )
62{
63 memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010064
65#if defined(MBEDTLS_THREADING_C)
66 mbedtls_mutex_init( &ctx->mutex );
67#endif
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +020068}
69
70/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010071 * HMAC_DRBG update, using optional additional data (10.1.2.2)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010072 */
Gilles Peskinee0e9c572018-09-11 16:47:16 +020073int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx,
74 const unsigned char *additional,
75 size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010076{
Hanno Beckerd3827c72019-09-03 12:56:37 +010077 size_t md_len = mbedtls_md_get_size(
78 mbedtls_md_get_handle( &ctx->md_ctx ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010079 unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
80 unsigned char sep[1];
Arto Kinnunen5b366932019-11-20 16:13:13 +020081 volatile unsigned char flow_counter = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020082 unsigned char K[MBEDTLS_MD_MAX_SIZE];
Arto Kinnunen5b366932019-11-20 16:13:13 +020083 int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010084
85 for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
86 {
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010087 /* Step 1 or 4 */
Arto Kinnunen5b366932019-11-20 16:13:13 +020088 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +020089 if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
90 goto exit;
Arto Kinnunen5b366932019-11-20 16:13:13 +020091
92 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +020093 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
94 ctx->V, md_len ) ) != 0 )
95 goto exit;
Arto Kinnunen5b366932019-11-20 16:13:13 +020096
97 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +020098 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
99 sep, 1 ) ) != 0 )
100 goto exit;
Arto Kinnunen5b366932019-11-20 16:13:13 +0200101
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100102 if( rounds == 2 )
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200103 {
Arto Kinnunen5b366932019-11-20 16:13:13 +0200104 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200105 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
106 additional, add_len ) ) != 0 )
107 goto exit;
108 }
Arto Kinnunen5b366932019-11-20 16:13:13 +0200109
110 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200111 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, K ) ) != 0 )
112 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100113
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100114 /* Step 2 or 5 */
Arto Kinnunen5b366932019-11-20 16:13:13 +0200115 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200116 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ) ) != 0 )
117 goto exit;
Arto Kinnunen5b366932019-11-20 16:13:13 +0200118
119 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200120 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
121 ctx->V, md_len ) ) != 0 )
122 goto exit;
Arto Kinnunen5b366932019-11-20 16:13:13 +0200123
124 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200125 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
126 goto exit;
Arto Kinnunen5299a422019-11-25 16:19:25 +0200127 flow_counter++;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100128 }
Gilles Peskineafa80372018-09-11 15:35:41 +0200129
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200130exit:
Arto Kinnunen5b366932019-11-20 16:13:13 +0200131
Arto Kinnunen5299a422019-11-25 16:19:25 +0200132 mbedtls_platform_zeroize( K, sizeof( K ) );
133 /* Check for possible attack.
134 * Counters needs to have correct values when returning success
135 */
136 if ( ret != 0 )
137 return( ret ); // error case, return immediately
138
139 if ( ( ( flow_counter == 8 ) && ( sep[0] == 1 ) ) ||
140 ( ( flow_counter == 18 ) && ( sep[0] == 2 ) ) )
Arto Kinnunen5b366932019-11-20 16:13:13 +0200141 {
Arto Kinnunen5299a422019-11-25 16:19:25 +0200142 flow_counter = flow_counter - sep[0];
143 // Double check flow_counter
144 if ( ( flow_counter == 7 ) || ( flow_counter == 16 ) )
Arto Kinnunen5b366932019-11-20 16:13:13 +0200145 {
Arto Kinnunen5299a422019-11-25 16:19:25 +0200146 return ret; // success, return 0 from ret
Arto Kinnunen5b366932019-11-20 16:13:13 +0200147 }
148 }
149
Arto Kinnunen5299a422019-11-25 16:19:25 +0200150 return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100151}
152
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200153#if !defined(MBEDTLS_DEPRECATED_REMOVED)
154void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
155 const unsigned char *additional,
156 size_t add_len )
157{
158 (void) mbedtls_hmac_drbg_update_ret( ctx, additional, add_len );
159}
160#endif /* MBEDTLS_DEPRECATED_REMOVED */
161
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100162/*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100163 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100164 */
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200165int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
Arto Kinnunen5b366932019-11-20 16:13:13 +0200166 mbedtls_md_handle_t md_info,
167 const unsigned char *data, size_t data_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100168{
Arto Kinnunen5b366932019-11-20 16:13:13 +0200169 int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100170
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200171 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100172 return( ret );
173
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100174 /*
175 * Set initial working state.
176 * Use the V memory location, which is currently all 0, to initialize the
177 * MD context with an all-zero key. Then set V to its initial value.
178 */
Gilles Peskineb7f71c82018-09-11 16:54:57 +0200179 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V,
180 mbedtls_md_get_size( md_info ) ) ) != 0 )
181 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200182 memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100183
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200184 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, data, data_len ) ) != 0 )
185 return( ret );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100186
Arto Kinnunen5b366932019-11-20 16:13:13 +0200187 return( ret );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100188}
189
Hanno Becker31c95e12019-08-27 09:22:09 +0100190/*
191 * Internal function used both for seeding and reseeding the DRBG.
192 * Comments starting with arabic numbers refer to section 10.1.2.4
193 * of SP800-90A, while roman numbers refer to section 9.2.
194 */
Hanno Beckerb3a06e62019-08-27 09:21:44 +0100195static int hmac_drbg_reseed_core( mbedtls_hmac_drbg_context *ctx,
196 const unsigned char *additional, size_t len,
197 int use_nonce )
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100198{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200199 unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
Hanno Beckereab304c2019-08-26 15:29:14 +0100200 size_t seedlen = 0;
Arto Kinnunen5b366932019-11-20 16:13:13 +0200201 size_t total_entropy_len;
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200202 int ret;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100203
Arto Kinnunen5b366932019-11-20 16:13:13 +0200204 if( use_nonce == HMAC_NONCE_NO )
205 total_entropy_len = ctx->entropy_len;
206 else
207 total_entropy_len = ctx->entropy_len * 3 / 2;
208
209 /* III. Check input length */
210 if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
211 total_entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100212 {
Arto Kinnunen5b366932019-11-20 16:13:13 +0200213 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100214 }
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100215
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200216 memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100217
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100218 /* IV. Gather entropy_len bytes of entropy for the seed */
Gilles Peskineb7f71c82018-09-11 16:54:57 +0200219 if( ( ret = ctx->f_entropy( ctx->p_entropy,
220 seed, ctx->entropy_len ) ) != 0 )
Hanno Beckereab304c2019-08-26 15:29:14 +0100221 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200222 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
Hanno Beckereab304c2019-08-26 15:29:14 +0100223 }
224 seedlen += ctx->entropy_len;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100225
Hanno Becker31c95e12019-08-27 09:22:09 +0100226 /* For initial seeding, allow adding of nonce generated
227 * from the entropy source. See Sect 8.6.7 in SP800-90A. */
Arto Kinnunen5b366932019-11-20 16:13:13 +0200228 if( use_nonce == HMAC_NONCE_YES )
Hanno Beckereab304c2019-08-26 15:29:14 +0100229 {
230 /* Note: We don't merge the two calls to f_entropy() in order
231 * to avoid requesting too much entropy from f_entropy()
232 * at once. Specifically, if the underlying digest is not
233 * SHA-1, 3 / 2 * entropy_len is at least 36 Bytes, which
234 * is larger than the maximum of 32 Bytes that our own
235 * entropy source implementation can emit in a single
236 * call in configurations disabling SHA-512. */
237 if( ( ret = ctx->f_entropy( ctx->p_entropy,
238 seed + seedlen,
239 ctx->entropy_len / 2 ) ) != 0 )
240 {
241 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
242 }
243
244 seedlen += ctx->entropy_len / 2;
245 }
246
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100247
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100248 /* 1. Concatenate entropy and additional data if any */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100249 if( additional != NULL && len != 0 )
250 {
Teppo Järvelin91d79382019-10-02 09:09:31 +0300251 mbedtls_platform_memcpy( seed + seedlen, additional, len );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100252 seedlen += len;
253 }
254
255 /* 2. Update state */
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200256 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, seed, seedlen ) ) != 0 )
257 goto exit;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100258
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100259 /* 3. Reset reseed_counter */
260 ctx->reseed_counter = 1;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100261
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200262exit:
Arto Kinnunen5299a422019-11-25 16:19:25 +0200263
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100264 /* 4. Done */
Gilles Peskineafa80372018-09-11 15:35:41 +0200265 mbedtls_platform_zeroize( seed, seedlen );
Arto Kinnunen5299a422019-11-25 16:19:25 +0200266
267 if ( ret != 0 )
268 return ret;
269
270 if ( ret == 0 && ctx->reseed_counter == 1 )
271 {
272 /* All ok, return 0 from ret */
273 return ret;
274 }
275
276 return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100277}
278
279/*
Hanno Becker31c95e12019-08-27 09:22:09 +0100280 * HMAC_DRBG reseeding: 10.1.2.4 + 9.2
Hanno Beckereab304c2019-08-26 15:29:14 +0100281 */
282int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
283 const unsigned char *additional, size_t len )
284{
Arto Kinnunen5b366932019-11-20 16:13:13 +0200285 return( hmac_drbg_reseed_core( ctx, additional, len, HMAC_NONCE_NO ) );
Hanno Beckereab304c2019-08-26 15:29:14 +0100286}
287
288/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100289 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
Hanno Becker31c95e12019-08-27 09:22:09 +0100290 *
291 * The nonce is not passed as a separate parameter but extracted
292 * from the entropy source as suggested in 8.6.7.
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100293 */
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200294int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
Hanno Beckera5cedbc2019-07-17 11:21:02 +0100295 mbedtls_md_handle_t md_info,
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100296 int (*f_entropy)(void *, unsigned char *, size_t),
297 void *p_entropy,
298 const unsigned char *custom,
299 size_t len )
300{
301 int ret;
Hanno Beckereab304c2019-08-26 15:29:14 +0100302 size_t md_size;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100303
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200304 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100305 return( ret );
306
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200307 md_size = mbedtls_md_get_size( md_info );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100308
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100309 /*
310 * Set initial working state.
311 * Use the V memory location, which is currently all 0, to initialize the
312 * MD context with an all-zero key. Then set V to its initial value.
313 */
Gilles Peskineb7f71c82018-09-11 16:54:57 +0200314 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ) ) != 0 )
315 return( ret );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100316 memset( ctx->V, 0x01, md_size );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100317
318 ctx->f_entropy = f_entropy;
319 ctx->p_entropy = p_entropy;
320
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200321 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100322
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100323 /*
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100324 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
325 * each hash function, then according to SP800-90A rev1 10.1 table 2,
326 * min_entropy_len (in bits) is security_strength.
327 *
328 * (This also matches the sizes used in the NIST test vectors.)
329 */
Hanno Beckereab304c2019-08-26 15:29:14 +0100330 ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
331 md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
332 32; /* better (256+) -> 256 bits */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100333
Arto Kinnunen5b366932019-11-20 16:13:13 +0200334 if( ( ret = hmac_drbg_reseed_core( ctx, custom, len, HMAC_NONCE_YES ) ) != 0 )
Hanno Beckereab304c2019-08-26 15:29:14 +0100335 {
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100336 return( ret );
Hanno Beckereab304c2019-08-26 15:29:14 +0100337 }
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100338
Arto Kinnunen5b366932019-11-20 16:13:13 +0200339 return( ret );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100340}
341
342/*
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100343 * Set prediction resistance
344 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200345void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100346 int resistance )
347{
348 ctx->prediction_resistance = resistance;
349}
350
351/*
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100352 * Set entropy length grabbed for reseeds
353 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200354void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100355{
356 ctx->entropy_len = len;
357}
358
359/*
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100360 * Set reseed interval
361 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200362void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval )
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100363{
364 ctx->reseed_interval = interval;
365}
366
367/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100368 * HMAC_DRBG random function with optional additional data:
369 * 10.1.2.5 (arabic) + 9.3 (Roman)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100370 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200371int mbedtls_hmac_drbg_random_with_add( void *p_rng,
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100372 unsigned char *output, size_t out_len,
373 const unsigned char *additional, size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100374{
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100375 int ret;
Arto Kinnunen5b366932019-11-20 16:13:13 +0200376 volatile unsigned char *output_fi = output;
377 volatile size_t out_len_fi = out_len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200378 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
Hanno Beckerd3827c72019-09-03 12:56:37 +0100379 size_t md_len = mbedtls_md_get_size(
380 mbedtls_md_get_handle( &ctx->md_ctx ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100381 size_t left = out_len;
382 unsigned char *out = output;
383
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100384 /* II. Check request length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200385 if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST )
386 return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100387
388 /* III. Check input length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200389 if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
390 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100391
392 /* 1. (aka VII and IX) Check reseed counter and PR */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100393 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200394 ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100395 ctx->reseed_counter > ctx->reseed_interval ) )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100396 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200397 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100398 return( ret );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100399
400 add_len = 0; /* VII.4 */
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100401 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100402
403 /* 2. Use additional data if any */
404 if( additional != NULL && add_len != 0 )
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200405 {
406 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
407 additional, add_len ) ) != 0 )
408 goto exit;
409 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100410
411 /* 3, 4, 5. Generate bytes */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100412 while( left != 0 )
413 {
414 size_t use_len = left > md_len ? md_len : left;
415
Gilles Peskineb7f71c82018-09-11 16:54:57 +0200416 if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
417 goto exit;
418 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
419 ctx->V, md_len ) ) != 0 )
420 goto exit;
421 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
422 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100423
Teppo Järvelin91d79382019-10-02 09:09:31 +0300424 mbedtls_platform_memcpy( out, ctx->V, use_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100425 out += use_len;
426 left -= use_len;
427 }
428
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100429 /* 6. Update */
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200430 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
431 additional, add_len ) ) != 0 )
432 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100433
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100434 /* 7. Update reseed counter */
435 ctx->reseed_counter++;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100436
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200437exit:
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100438 /* 8. Done */
Arto Kinnunen5b366932019-11-20 16:13:13 +0200439
Arto Kinnunen5299a422019-11-25 16:19:25 +0200440 if ( ret != 0 )
441 return ret;
442
443 /*
444 * Check doubled variables and illegal conditions in case of possible
445 * attack.
446 */
447 if ( ( out_len_fi == out_len ) && ( output_fi == output) &&
448 ( left == 0 ) )
Arto Kinnunen5b366932019-11-20 16:13:13 +0200449 {
Arto Kinnunen5299a422019-11-25 16:19:25 +0200450 return ret; // Success, return 0
Arto Kinnunen5b366932019-11-20 16:13:13 +0200451 }
452
Arto Kinnunen5299a422019-11-25 16:19:25 +0200453 return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100454}
455
456/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100457 * HMAC_DRBG random function
458 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200459int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100460{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100461 int ret;
462 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
463
464#if defined(MBEDTLS_THREADING_C)
465 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
466 return( ret );
467#endif
468
469 ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
470
471#if defined(MBEDTLS_THREADING_C)
472 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
473 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
474#endif
475
476 return( ret );
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100477}
478
479/*
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100480 * Free an HMAC_DRBG context
481 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200482void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100483{
484 if( ctx == NULL )
485 return;
486
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100487#if defined(MBEDTLS_THREADING_C)
488 mbedtls_mutex_free( &ctx->mutex );
489#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200490 mbedtls_md_free( &ctx->md_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500491 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100492}
493
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200494#if defined(MBEDTLS_FS_IO)
495int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100496{
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100497 int ret;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100498 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200499 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100500
501 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200502 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100503
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200504 if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100505 goto exit;
506
507 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
508 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200509 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
Paul Bakker4c284c92014-03-26 15:33:05 +0100510 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100511 }
512
513 ret = 0;
514
515exit:
516 fclose( f );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500517 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100518
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100519 return( ret );
520}
521
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200522int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100523{
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100524 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200525 FILE *f = NULL;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100526 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200527 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200528 unsigned char c;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100529
530 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200531 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100532
Gilles Peskine82204662018-09-11 18:43:09 +0200533 n = fread( buf, 1, sizeof( buf ), f );
534 if( fread( &c, 1, 1, f ) != 0 )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100535 {
Gilles Peskine82204662018-09-11 18:43:09 +0200536 ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
537 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100538 }
Gilles Peskine82204662018-09-11 18:43:09 +0200539 if( n == 0 || ferror( f ) )
540 {
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100541 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200542 goto exit;
543 }
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100544 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200545 f = NULL;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100546
Gilles Peskine82204662018-09-11 18:43:09 +0200547 ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n );
548
549exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500550 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200551 if( f != NULL )
552 fclose( f );
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100553 if( ret != 0 )
554 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200555 return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100556}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200557#endif /* MBEDTLS_FS_IO */
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100558
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100559
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200560#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100561
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200562#if !defined(MBEDTLS_SHA1_C)
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100563/* Dummy checkup routine */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200564int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100565{
Manuel Pégourié-Gonnardd1004f02015-08-07 10:46:54 +0200566 (void) verbose;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100567 return( 0 );
568}
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100569#else
570
571#define OUTPUT_LEN 80
572
573/* From a NIST PR=true test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000574static const unsigned char entropy_pr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100575 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
576 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
577 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
578 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
579 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
580static const unsigned char result_pr[OUTPUT_LEN] = {
581 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
582 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
583 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
584 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
585 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
586 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
587 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
588
589/* From a NIST PR=false test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000590static const unsigned char entropy_nopr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100591 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
592 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
593 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
594 0xe9, 0x9d, 0xfe, 0xdf };
595static const unsigned char result_nopr[OUTPUT_LEN] = {
596 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
597 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
598 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
599 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
600 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
601 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
602 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
603
604/* "Entropy" from buffer */
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100605static size_t test_offset;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100606static int hmac_drbg_self_test_entropy( void *data,
607 unsigned char *buf, size_t len )
608{
609 const unsigned char *p = data;
Teppo Järvelinb5c46712019-10-04 13:35:55 +0300610 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100611 test_offset += len;
612 return( 0 );
613}
614
Paul Bakker7dc4c442014-02-01 22:50:26 +0100615#define CHK( c ) if( (c) != 0 ) \
616 { \
617 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200618 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100619 return( 1 ); \
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100620 }
621
622/*
623 * Checkup routine for HMAC_DRBG with SHA-1
624 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200625int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100626{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200627 mbedtls_hmac_drbg_context ctx;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100628 unsigned char buf[OUTPUT_LEN];
Hanno Beckera5cedbc2019-07-17 11:21:02 +0100629 mbedtls_md_handle_t md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100630
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200631 mbedtls_hmac_drbg_init( &ctx );
632
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100633 /*
634 * PR = True
635 */
636 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200637 mbedtls_printf( " HMAC_DRBG (PR = True) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100638
639 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200640 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000641 hmac_drbg_self_test_entropy, (void *) entropy_pr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100642 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200643 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
644 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
645 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100646 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200647 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100648
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100649 mbedtls_hmac_drbg_free( &ctx );
650
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100651 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200652 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100653
654 /*
655 * PR = False
656 */
657 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200658 mbedtls_printf( " HMAC_DRBG (PR = False) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100659
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100660 mbedtls_hmac_drbg_init( &ctx );
661
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100662 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200663 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000664 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100665 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200666 CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
667 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
668 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100669 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200670 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100671
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100672 mbedtls_hmac_drbg_free( &ctx );
673
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100674 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200675 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100676
677 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200678 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100679
680 return( 0 );
681}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200682#endif /* MBEDTLS_SHA1_C */
683#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100684
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200685#endif /* MBEDTLS_HMAC_DRBG_C */