blob: ecca880348558fd85016ea4cdc289700b46e796b [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 Kinnunenec37a892019-11-28 13:40:32 +020081 volatile unsigned int 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;
Andrzej Kurek74f7d0f2020-07-06 14:28:12 -040084 volatile const unsigned char *additional_dup = additional;
85 volatile size_t add_len_dup = add_len;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010086
87 for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
88 {
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010089 /* Step 1 or 4 */
Arto Kinnunen5b366932019-11-20 16:13:13 +020090 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +020091 if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
92 goto exit;
Arto Kinnunen5b366932019-11-20 16:13:13 +020093
94 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +020095 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
96 ctx->V, md_len ) ) != 0 )
97 goto exit;
Arto Kinnunen5b366932019-11-20 16:13:13 +020098
99 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200100 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
101 sep, 1 ) ) != 0 )
102 goto exit;
Arto Kinnunen5b366932019-11-20 16:13:13 +0200103
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100104 if( rounds == 2 )
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200105 {
Arto Kinnunen5b366932019-11-20 16:13:13 +0200106 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200107 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
108 additional, add_len ) ) != 0 )
109 goto exit;
110 }
Arto Kinnunen5b366932019-11-20 16:13:13 +0200111
112 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200113 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, K ) ) != 0 )
114 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100115
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100116 /* Step 2 or 5 */
Arto Kinnunen5b366932019-11-20 16:13:13 +0200117 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200118 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ) ) != 0 )
119 goto exit;
Arto Kinnunen5b366932019-11-20 16:13:13 +0200120
121 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200122 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
123 ctx->V, md_len ) ) != 0 )
124 goto exit;
Arto Kinnunen5b366932019-11-20 16:13:13 +0200125
126 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200127 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
128 goto exit;
Arto Kinnunen5299a422019-11-25 16:19:25 +0200129 flow_counter++;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100130 }
Gilles Peskineafa80372018-09-11 15:35:41 +0200131
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200132exit:
Arto Kinnunen5b366932019-11-20 16:13:13 +0200133
Arto Kinnunen5299a422019-11-25 16:19:25 +0200134 mbedtls_platform_zeroize( K, sizeof( K ) );
135 /* Check for possible attack.
136 * Counters needs to have correct values when returning success
137 */
138 if ( ret != 0 )
139 return( ret ); // error case, return immediately
140
141 if ( ( ( flow_counter == 8 ) && ( sep[0] == 1 ) ) ||
142 ( ( flow_counter == 18 ) && ( sep[0] == 2 ) ) )
Arto Kinnunen5b366932019-11-20 16:13:13 +0200143 {
Arto Kinnunen5299a422019-11-25 16:19:25 +0200144 flow_counter = flow_counter - sep[0];
145 // Double check flow_counter
146 if ( ( flow_counter == 7 ) || ( flow_counter == 16 ) )
Arto Kinnunen5b366932019-11-20 16:13:13 +0200147 {
Andrzej Kurek74f7d0f2020-07-06 14:28:12 -0400148 if( additional_dup == additional && add_len_dup == add_len )
149 {
150 return ret; // success, return 0 from ret
151 }
Arto Kinnunen5b366932019-11-20 16:13:13 +0200152 }
153 }
154
Arto Kinnunen5299a422019-11-25 16:19:25 +0200155 return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100156}
157
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200158#if !defined(MBEDTLS_DEPRECATED_REMOVED)
159void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
160 const unsigned char *additional,
161 size_t add_len )
162{
163 (void) mbedtls_hmac_drbg_update_ret( ctx, additional, add_len );
164}
165#endif /* MBEDTLS_DEPRECATED_REMOVED */
166
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100167/*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100168 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100169 */
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200170int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
Arto Kinnunen5b366932019-11-20 16:13:13 +0200171 mbedtls_md_handle_t md_info,
172 const unsigned char *data, size_t data_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100173{
Arto Kinnunen5b366932019-11-20 16:13:13 +0200174 int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
Andrzej Kurek74f7d0f2020-07-06 14:28:12 -0400175 volatile const unsigned char *data_dup = data;
176 volatile size_t data_len_dup = data_len;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100177
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200178 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100179 return( ret );
180
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100181 /*
182 * Set initial working state.
183 * Use the V memory location, which is currently all 0, to initialize the
184 * MD context with an all-zero key. Then set V to its initial value.
185 */
Gilles Peskineb7f71c82018-09-11 16:54:57 +0200186 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V,
187 mbedtls_md_get_size( md_info ) ) ) != 0 )
188 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200189 memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100190
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200191 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, data, data_len ) ) != 0 )
192 return( ret );
Andrzej Kurek74f7d0f2020-07-06 14:28:12 -0400193 if( data_dup != data || data_len_dup != data_len )
194 {
195 ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
196 }
Arto Kinnunen5b366932019-11-20 16:13:13 +0200197 return( ret );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100198}
199
Hanno Becker31c95e12019-08-27 09:22:09 +0100200/*
201 * Internal function used both for seeding and reseeding the DRBG.
202 * Comments starting with arabic numbers refer to section 10.1.2.4
203 * of SP800-90A, while roman numbers refer to section 9.2.
204 */
Hanno Beckerb3a06e62019-08-27 09:21:44 +0100205static int hmac_drbg_reseed_core( mbedtls_hmac_drbg_context *ctx,
206 const unsigned char *additional, size_t len,
207 int use_nonce )
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100208{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200209 unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
Hanno Beckereab304c2019-08-26 15:29:14 +0100210 size_t seedlen = 0;
Arto Kinnunen5b366932019-11-20 16:13:13 +0200211 size_t total_entropy_len;
Andrzej Kurekfd56f402020-05-25 11:52:05 -0400212 int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
Andrzej Kurek74f7d0f2020-07-06 14:28:12 -0400213 volatile const unsigned char *additional_dup = additional;
214 volatile size_t len_dup = len;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100215
Arto Kinnunen5b366932019-11-20 16:13:13 +0200216 if( use_nonce == HMAC_NONCE_NO )
217 total_entropy_len = ctx->entropy_len;
218 else
219 total_entropy_len = ctx->entropy_len * 3 / 2;
220
221 /* III. Check input length */
222 if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
223 total_entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100224 {
Arto Kinnunen5b366932019-11-20 16:13:13 +0200225 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100226 }
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100227
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200228 memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100229
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100230 /* IV. Gather entropy_len bytes of entropy for the seed */
Gilles Peskineb7f71c82018-09-11 16:54:57 +0200231 if( ( ret = ctx->f_entropy( ctx->p_entropy,
232 seed, ctx->entropy_len ) ) != 0 )
Hanno Beckereab304c2019-08-26 15:29:14 +0100233 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200234 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
Hanno Beckereab304c2019-08-26 15:29:14 +0100235 }
236 seedlen += ctx->entropy_len;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100237
Hanno Becker31c95e12019-08-27 09:22:09 +0100238 /* For initial seeding, allow adding of nonce generated
239 * from the entropy source. See Sect 8.6.7 in SP800-90A. */
Arto Kinnunen5b366932019-11-20 16:13:13 +0200240 if( use_nonce == HMAC_NONCE_YES )
Hanno Beckereab304c2019-08-26 15:29:14 +0100241 {
242 /* Note: We don't merge the two calls to f_entropy() in order
243 * to avoid requesting too much entropy from f_entropy()
244 * at once. Specifically, if the underlying digest is not
245 * SHA-1, 3 / 2 * entropy_len is at least 36 Bytes, which
246 * is larger than the maximum of 32 Bytes that our own
247 * entropy source implementation can emit in a single
248 * call in configurations disabling SHA-512. */
249 if( ( ret = ctx->f_entropy( ctx->p_entropy,
250 seed + seedlen,
251 ctx->entropy_len / 2 ) ) != 0 )
252 {
253 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
254 }
255
256 seedlen += ctx->entropy_len / 2;
257 }
258
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100259
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100260 /* 1. Concatenate entropy and additional data if any */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100261 if( additional != NULL && len != 0 )
262 {
Teppo Järvelin91d79382019-10-02 09:09:31 +0300263 mbedtls_platform_memcpy( seed + seedlen, additional, len );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100264 seedlen += len;
265 }
266
267 /* 2. Update state */
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200268 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, seed, seedlen ) ) != 0 )
269 goto exit;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100270
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100271 /* 3. Reset reseed_counter */
272 ctx->reseed_counter = 1;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100273
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200274exit:
Arto Kinnunen5299a422019-11-25 16:19:25 +0200275
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100276 /* 4. Done */
Gilles Peskineafa80372018-09-11 15:35:41 +0200277 mbedtls_platform_zeroize( seed, seedlen );
Arto Kinnunen5299a422019-11-25 16:19:25 +0200278
Andrzej Kurek74f7d0f2020-07-06 14:28:12 -0400279 if( additional_dup != additional || len_dup != len )
280 {
281 return MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
282 }
283
Arto Kinnunen5299a422019-11-25 16:19:25 +0200284 if ( ret != 0 )
285 return ret;
286
287 if ( ret == 0 && ctx->reseed_counter == 1 )
288 {
289 /* All ok, return 0 from ret */
290 return ret;
291 }
292
293 return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100294}
295
296/*
Hanno Becker31c95e12019-08-27 09:22:09 +0100297 * HMAC_DRBG reseeding: 10.1.2.4 + 9.2
Hanno Beckereab304c2019-08-26 15:29:14 +0100298 */
299int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
300 const unsigned char *additional, size_t len )
301{
Arto Kinnunen5b366932019-11-20 16:13:13 +0200302 return( hmac_drbg_reseed_core( ctx, additional, len, HMAC_NONCE_NO ) );
Hanno Beckereab304c2019-08-26 15:29:14 +0100303}
304
305/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100306 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
Hanno Becker31c95e12019-08-27 09:22:09 +0100307 *
308 * The nonce is not passed as a separate parameter but extracted
309 * from the entropy source as suggested in 8.6.7.
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100310 */
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200311int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
Hanno Beckera5cedbc2019-07-17 11:21:02 +0100312 mbedtls_md_handle_t md_info,
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100313 int (*f_entropy)(void *, unsigned char *, size_t),
314 void *p_entropy,
315 const unsigned char *custom,
316 size_t len )
317{
Andrzej Kurekfd56f402020-05-25 11:52:05 -0400318 int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
Andrzej Kurek74f7d0f2020-07-06 14:28:12 -0400319 int (* volatile f_entropy_dup)(void *, unsigned char *, size_t) = f_entropy;
320 volatile void *p_entropy_dup = p_entropy;
321 volatile const unsigned char *custom_dup = custom;
322 volatile size_t len_dup = len;
323
Hanno Beckereab304c2019-08-26 15:29:14 +0100324 size_t md_size;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100325
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200326 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100327 return( ret );
328
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200329 md_size = mbedtls_md_get_size( md_info );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100330
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100331 /*
332 * Set initial working state.
333 * Use the V memory location, which is currently all 0, to initialize the
334 * MD context with an all-zero key. Then set V to its initial value.
335 */
Gilles Peskineb7f71c82018-09-11 16:54:57 +0200336 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ) ) != 0 )
337 return( ret );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100338 memset( ctx->V, 0x01, md_size );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100339
340 ctx->f_entropy = f_entropy;
341 ctx->p_entropy = p_entropy;
342
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200343 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100344
Gilles Peskine1d2a9e82019-10-04 11:47:35 +0200345 if( ctx->entropy_len == 0 )
346 {
347 /*
348 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
349 * each hash function, then according to SP800-90A rev1 10.1 table 2,
350 * min_entropy_len (in bits) is security_strength.
351 *
352 * (This also matches the sizes used in the NIST test vectors.)
353 */
354 ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
355 md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
356 32; /* better (256+) -> 256 bits */
357 }
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100358
Arto Kinnunen5b366932019-11-20 16:13:13 +0200359 if( ( ret = hmac_drbg_reseed_core( ctx, custom, len, HMAC_NONCE_YES ) ) != 0 )
Hanno Beckereab304c2019-08-26 15:29:14 +0100360 {
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100361 return( ret );
Hanno Beckereab304c2019-08-26 15:29:14 +0100362 }
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100363
Andrzej Kurek74f7d0f2020-07-06 14:28:12 -0400364 if( f_entropy != f_entropy_dup || p_entropy != p_entropy_dup ||
365 custom_dup != custom || len_dup != len )
366 {
367 ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
368 }
Arto Kinnunen5b366932019-11-20 16:13:13 +0200369 return( ret );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100370}
371
372/*
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100373 * Set prediction resistance
374 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200375void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100376 int resistance )
377{
378 ctx->prediction_resistance = resistance;
379}
380
381/*
Gilles Peskine1d2a9e82019-10-04 11:47:35 +0200382 * Set entropy length grabbed for seeding
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100383 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200384void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100385{
386 ctx->entropy_len = len;
387}
388
389/*
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100390 * Set reseed interval
391 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200392void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval )
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100393{
394 ctx->reseed_interval = interval;
395}
396
397/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100398 * HMAC_DRBG random function with optional additional data:
399 * 10.1.2.5 (arabic) + 9.3 (Roman)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100400 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200401int mbedtls_hmac_drbg_random_with_add( void *p_rng,
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100402 unsigned char *output, size_t out_len,
403 const unsigned char *additional, size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100404{
Andrzej Kurekfd56f402020-05-25 11:52:05 -0400405 int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
Arto Kinnunen5b366932019-11-20 16:13:13 +0200406 volatile unsigned char *output_fi = output;
407 volatile size_t out_len_fi = out_len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200408 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
Hanno Beckerd3827c72019-09-03 12:56:37 +0100409 size_t md_len = mbedtls_md_get_size(
410 mbedtls_md_get_handle( &ctx->md_ctx ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100411 size_t left = out_len;
412 unsigned char *out = output;
413
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100414 /* II. Check request length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200415 if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST )
416 return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100417
418 /* III. Check input length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200419 if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
420 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100421
422 /* 1. (aka VII and IX) Check reseed counter and PR */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100423 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200424 ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100425 ctx->reseed_counter > ctx->reseed_interval ) )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100426 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200427 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100428 return( ret );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100429
430 add_len = 0; /* VII.4 */
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100431 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100432
433 /* 2. Use additional data if any */
434 if( additional != NULL && add_len != 0 )
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200435 {
436 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
437 additional, add_len ) ) != 0 )
438 goto exit;
439 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100440
441 /* 3, 4, 5. Generate bytes */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100442 while( left != 0 )
443 {
444 size_t use_len = left > md_len ? md_len : left;
445
Gilles Peskineb7f71c82018-09-11 16:54:57 +0200446 if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
447 goto exit;
448 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
449 ctx->V, md_len ) ) != 0 )
450 goto exit;
451 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
452 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100453
Teppo Järvelin91d79382019-10-02 09:09:31 +0300454 mbedtls_platform_memcpy( out, ctx->V, use_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100455 out += use_len;
456 left -= use_len;
457 }
458
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100459 /* 6. Update */
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200460 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
461 additional, add_len ) ) != 0 )
462 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100463
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100464 /* 7. Update reseed counter */
465 ctx->reseed_counter++;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100466
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200467exit:
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100468 /* 8. Done */
Arto Kinnunen5b366932019-11-20 16:13:13 +0200469
Arto Kinnunen5299a422019-11-25 16:19:25 +0200470 if ( ret != 0 )
471 return ret;
472
473 /*
474 * Check doubled variables and illegal conditions in case of possible
475 * attack.
476 */
477 if ( ( out_len_fi == out_len ) && ( output_fi == output) &&
478 ( left == 0 ) )
Arto Kinnunen5b366932019-11-20 16:13:13 +0200479 {
Arto Kinnunen5299a422019-11-25 16:19:25 +0200480 return ret; // Success, return 0
Arto Kinnunen5b366932019-11-20 16:13:13 +0200481 }
482
Arto Kinnunen5299a422019-11-25 16:19:25 +0200483 return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100484}
485
486/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100487 * HMAC_DRBG random function
488 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200489int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100490{
Andrzej Kurekfd56f402020-05-25 11:52:05 -0400491 int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100492 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
493
494#if defined(MBEDTLS_THREADING_C)
495 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
496 return( ret );
497#endif
498
499 ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
500
501#if defined(MBEDTLS_THREADING_C)
502 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
503 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
504#endif
505
506 return( ret );
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100507}
508
509/*
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100510 * Free an HMAC_DRBG context
511 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200512void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100513{
514 if( ctx == NULL )
515 return;
516
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100517#if defined(MBEDTLS_THREADING_C)
518 mbedtls_mutex_free( &ctx->mutex );
519#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200520 mbedtls_md_free( &ctx->md_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500521 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100522}
523
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200524#if defined(MBEDTLS_FS_IO)
525int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100526{
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100527 int ret;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100528 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200529 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100530
531 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200532 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100533
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200534 if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100535 goto exit;
536
537 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
538 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200539 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
Paul Bakker4c284c92014-03-26 15:33:05 +0100540 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100541 }
542
543 ret = 0;
544
545exit:
546 fclose( f );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500547 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100548
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100549 return( ret );
550}
551
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200552int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100553{
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100554 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200555 FILE *f = NULL;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100556 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200557 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200558 unsigned char c;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100559
560 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200561 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100562
Gilles Peskine82204662018-09-11 18:43:09 +0200563 n = fread( buf, 1, sizeof( buf ), f );
564 if( fread( &c, 1, 1, f ) != 0 )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100565 {
Gilles Peskine82204662018-09-11 18:43:09 +0200566 ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
567 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100568 }
Gilles Peskine82204662018-09-11 18:43:09 +0200569 if( n == 0 || ferror( f ) )
570 {
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100571 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200572 goto exit;
573 }
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100574 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200575 f = NULL;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100576
Gilles Peskine82204662018-09-11 18:43:09 +0200577 ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n );
578
579exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500580 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200581 if( f != NULL )
582 fclose( f );
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100583 if( ret != 0 )
584 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200585 return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100586}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200587#endif /* MBEDTLS_FS_IO */
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100588
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100589
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200590#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100591
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200592#if !defined(MBEDTLS_SHA1_C)
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100593/* Dummy checkup routine */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200594int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100595{
Manuel Pégourié-Gonnardd1004f02015-08-07 10:46:54 +0200596 (void) verbose;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100597 return( 0 );
598}
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100599#else
600
601#define OUTPUT_LEN 80
602
603/* From a NIST PR=true test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000604static const unsigned char entropy_pr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100605 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
606 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
607 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
608 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
609 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
610static const unsigned char result_pr[OUTPUT_LEN] = {
611 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
612 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
613 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
614 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
615 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
616 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
617 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
618
619/* From a NIST PR=false test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000620static const unsigned char entropy_nopr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100621 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
622 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
623 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
624 0xe9, 0x9d, 0xfe, 0xdf };
625static const unsigned char result_nopr[OUTPUT_LEN] = {
626 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
627 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
628 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
629 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
630 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
631 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
632 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
633
634/* "Entropy" from buffer */
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100635static size_t test_offset;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100636static int hmac_drbg_self_test_entropy( void *data,
637 unsigned char *buf, size_t len )
638{
639 const unsigned char *p = data;
Teppo Järvelinb5c46712019-10-04 13:35:55 +0300640 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100641 test_offset += len;
642 return( 0 );
643}
644
Paul Bakker7dc4c442014-02-01 22:50:26 +0100645#define CHK( c ) if( (c) != 0 ) \
646 { \
647 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200648 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100649 return( 1 ); \
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100650 }
651
652/*
653 * Checkup routine for HMAC_DRBG with SHA-1
654 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200655int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100656{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200657 mbedtls_hmac_drbg_context ctx;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100658 unsigned char buf[OUTPUT_LEN];
Hanno Beckera5cedbc2019-07-17 11:21:02 +0100659 mbedtls_md_handle_t md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100660
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200661 mbedtls_hmac_drbg_init( &ctx );
662
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100663 /*
664 * PR = True
665 */
666 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200667 mbedtls_printf( " HMAC_DRBG (PR = True) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100668
669 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200670 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000671 hmac_drbg_self_test_entropy, (void *) entropy_pr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100672 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200673 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
674 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
675 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100676 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200677 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100678
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100679 mbedtls_hmac_drbg_free( &ctx );
680
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100681 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200682 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100683
684 /*
685 * PR = False
686 */
687 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200688 mbedtls_printf( " HMAC_DRBG (PR = False) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100689
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100690 mbedtls_hmac_drbg_init( &ctx );
691
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100692 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200693 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000694 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100695 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200696 CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
697 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
698 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100699 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200700 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100701
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100702 mbedtls_hmac_drbg_free( &ctx );
703
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100704 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200705 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100706
707 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200708 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100709
710 return( 0 );
711}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200712#endif /* MBEDTLS_SHA1_C */
713#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100714
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200715#endif /* MBEDTLS_HMAC_DRBG_C */