blob: d8669c3c412256b592c12ef1cb39c9e606081408 [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
Andrzej Kurekf6265442020-07-18 07:09:04 -040065 ctx->prediction_resistance = MBEDTLS_HMAC_DRBG_PR_OFF;
Andrzej Kurek4353b692020-07-19 04:58:58 -040066 ctx->reseed_flag = MBEDTLS_HMAC_DRBG_RESEED;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010067#if defined(MBEDTLS_THREADING_C)
68 mbedtls_mutex_init( &ctx->mutex );
69#endif
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +020070}
71
72/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010073 * HMAC_DRBG update, using optional additional data (10.1.2.2)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010074 */
Gilles Peskinee0e9c572018-09-11 16:47:16 +020075int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx,
76 const unsigned char *additional,
77 size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010078{
Hanno Beckerd3827c72019-09-03 12:56:37 +010079 size_t md_len = mbedtls_md_get_size(
80 mbedtls_md_get_handle( &ctx->md_ctx ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010081 unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
82 unsigned char sep[1];
Arto Kinnunenec37a892019-11-28 13:40:32 +020083 volatile unsigned int flow_counter = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020084 unsigned char K[MBEDTLS_MD_MAX_SIZE];
Arto Kinnunen5b366932019-11-20 16:13:13 +020085 int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
Andrzej Kurek74f7d0f2020-07-06 14:28:12 -040086 volatile const unsigned char *additional_dup = additional;
87 volatile size_t add_len_dup = add_len;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010088
89 for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
90 {
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010091 /* Step 1 or 4 */
Arto Kinnunen5b366932019-11-20 16:13:13 +020092 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +020093 if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 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 ctx->V, md_len ) ) != 0 )
99 goto exit;
Arto Kinnunen5b366932019-11-20 16:13:13 +0200100
101 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200102 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
103 sep, 1 ) ) != 0 )
104 goto exit;
Arto Kinnunen5b366932019-11-20 16:13:13 +0200105
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100106 if( rounds == 2 )
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200107 {
Arto Kinnunen5b366932019-11-20 16:13:13 +0200108 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200109 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
110 additional, add_len ) ) != 0 )
111 goto exit;
112 }
Arto Kinnunen5b366932019-11-20 16:13:13 +0200113
114 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200115 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, K ) ) != 0 )
116 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100117
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100118 /* Step 2 or 5 */
Arto Kinnunen5b366932019-11-20 16:13:13 +0200119 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200120 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, K, 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_update( &ctx->md_ctx,
125 ctx->V, md_len ) ) != 0 )
126 goto exit;
Arto Kinnunen5b366932019-11-20 16:13:13 +0200127
128 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200129 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
130 goto exit;
Arto Kinnunen5299a422019-11-25 16:19:25 +0200131 flow_counter++;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100132 }
Gilles Peskineafa80372018-09-11 15:35:41 +0200133
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200134exit:
Arto Kinnunen5b366932019-11-20 16:13:13 +0200135
Arto Kinnunen5299a422019-11-25 16:19:25 +0200136 mbedtls_platform_zeroize( K, sizeof( K ) );
137 /* Check for possible attack.
138 * Counters needs to have correct values when returning success
139 */
140 if ( ret != 0 )
141 return( ret ); // error case, return immediately
142
143 if ( ( ( flow_counter == 8 ) && ( sep[0] == 1 ) ) ||
144 ( ( flow_counter == 18 ) && ( sep[0] == 2 ) ) )
Arto Kinnunen5b366932019-11-20 16:13:13 +0200145 {
Arto Kinnunen5299a422019-11-25 16:19:25 +0200146 flow_counter = flow_counter - sep[0];
147 // Double check flow_counter
148 if ( ( flow_counter == 7 ) || ( flow_counter == 16 ) )
Arto Kinnunen5b366932019-11-20 16:13:13 +0200149 {
Andrzej Kurek74f7d0f2020-07-06 14:28:12 -0400150 if( additional_dup == additional && add_len_dup == add_len )
151 {
152 return ret; // success, return 0 from ret
153 }
Arto Kinnunen5b366932019-11-20 16:13:13 +0200154 }
155 }
156
Arto Kinnunen5299a422019-11-25 16:19:25 +0200157 return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100158}
159
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200160#if !defined(MBEDTLS_DEPRECATED_REMOVED)
161void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
162 const unsigned char *additional,
163 size_t add_len )
164{
165 (void) mbedtls_hmac_drbg_update_ret( ctx, additional, add_len );
166}
167#endif /* MBEDTLS_DEPRECATED_REMOVED */
168
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100169/*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100170 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100171 */
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200172int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
Arto Kinnunen5b366932019-11-20 16:13:13 +0200173 mbedtls_md_handle_t md_info,
174 const unsigned char *data, size_t data_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100175{
Arto Kinnunen5b366932019-11-20 16:13:13 +0200176 int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
Andrzej Kurek74f7d0f2020-07-06 14:28:12 -0400177 volatile const unsigned char *data_dup = data;
178 volatile size_t data_len_dup = data_len;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100179
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200180 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100181 return( ret );
182
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100183 /*
184 * Set initial working state.
185 * Use the V memory location, which is currently all 0, to initialize the
186 * MD context with an all-zero key. Then set V to its initial value.
187 */
Gilles Peskineb7f71c82018-09-11 16:54:57 +0200188 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V,
189 mbedtls_md_get_size( md_info ) ) ) != 0 )
190 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200191 memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100192
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200193 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, data, data_len ) ) != 0 )
194 return( ret );
Andrzej Kurek74f7d0f2020-07-06 14:28:12 -0400195 if( data_dup != data || data_len_dup != data_len )
196 {
197 ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
198 }
Arto Kinnunen5b366932019-11-20 16:13:13 +0200199 return( ret );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100200}
201
Hanno Becker31c95e12019-08-27 09:22:09 +0100202/*
203 * Internal function used both for seeding and reseeding the DRBG.
204 * Comments starting with arabic numbers refer to section 10.1.2.4
205 * of SP800-90A, while roman numbers refer to section 9.2.
206 */
Hanno Beckerb3a06e62019-08-27 09:21:44 +0100207static int hmac_drbg_reseed_core( mbedtls_hmac_drbg_context *ctx,
208 const unsigned char *additional, size_t len,
209 int use_nonce )
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100210{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200211 unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
Hanno Beckereab304c2019-08-26 15:29:14 +0100212 size_t seedlen = 0;
Arto Kinnunen5b366932019-11-20 16:13:13 +0200213 size_t total_entropy_len;
Andrzej Kurekfd56f402020-05-25 11:52:05 -0400214 int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
Andrzej Kurek9167aa92020-07-18 00:10:50 -0400215 const unsigned char * volatile additional_dup = additional;
Andrzej Kurek74f7d0f2020-07-06 14:28:12 -0400216 volatile size_t len_dup = len;
Andrzej Kurekca609372020-07-08 03:19:02 -0400217 int reseed_counter_backup = -1;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100218
Arto Kinnunen5b366932019-11-20 16:13:13 +0200219 if( use_nonce == HMAC_NONCE_NO )
220 total_entropy_len = ctx->entropy_len;
221 else
222 total_entropy_len = ctx->entropy_len * 3 / 2;
223
224 /* III. Check input length */
225 if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
226 total_entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100227 {
Arto Kinnunen5b366932019-11-20 16:13:13 +0200228 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100229 }
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100230
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200231 memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100232
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100233 /* IV. Gather entropy_len bytes of entropy for the seed */
Gilles Peskineb7f71c82018-09-11 16:54:57 +0200234 if( ( ret = ctx->f_entropy( ctx->p_entropy,
235 seed, ctx->entropy_len ) ) != 0 )
Hanno Beckereab304c2019-08-26 15:29:14 +0100236 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200237 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
Hanno Beckereab304c2019-08-26 15:29:14 +0100238 }
239 seedlen += ctx->entropy_len;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100240
Hanno Becker31c95e12019-08-27 09:22:09 +0100241 /* For initial seeding, allow adding of nonce generated
242 * from the entropy source. See Sect 8.6.7 in SP800-90A. */
Arto Kinnunen5b366932019-11-20 16:13:13 +0200243 if( use_nonce == HMAC_NONCE_YES )
Hanno Beckereab304c2019-08-26 15:29:14 +0100244 {
245 /* Note: We don't merge the two calls to f_entropy() in order
246 * to avoid requesting too much entropy from f_entropy()
247 * at once. Specifically, if the underlying digest is not
248 * SHA-1, 3 / 2 * entropy_len is at least 36 Bytes, which
249 * is larger than the maximum of 32 Bytes that our own
250 * entropy source implementation can emit in a single
251 * call in configurations disabling SHA-512. */
252 if( ( ret = ctx->f_entropy( ctx->p_entropy,
253 seed + seedlen,
254 ctx->entropy_len / 2 ) ) != 0 )
255 {
256 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
257 }
258
259 seedlen += ctx->entropy_len / 2;
260 }
261
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100262
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100263 /* 1. Concatenate entropy and additional data if any */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100264 if( additional != NULL && len != 0 )
265 {
Teppo Järvelin91d79382019-10-02 09:09:31 +0300266 mbedtls_platform_memcpy( seed + seedlen, additional, len );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100267 seedlen += len;
268 }
269
270 /* 2. Update state */
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200271 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, seed, seedlen ) ) != 0 )
272 goto exit;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100273
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100274 /* 3. Reset reseed_counter */
Andrzej Kurekca609372020-07-08 03:19:02 -0400275 reseed_counter_backup = ctx->reseed_counter;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100276 ctx->reseed_counter = 1;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100277
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200278exit:
Arto Kinnunen5299a422019-11-25 16:19:25 +0200279
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100280 /* 4. Done */
Gilles Peskineafa80372018-09-11 15:35:41 +0200281 mbedtls_platform_zeroize( seed, seedlen );
Arto Kinnunen5299a422019-11-25 16:19:25 +0200282
Andrzej Kurek74f7d0f2020-07-06 14:28:12 -0400283 if( additional_dup != additional || len_dup != len )
284 {
Andrzej Kurekca609372020-07-08 03:19:02 -0400285 /* Rollback the reseed_counter in case of FI */
286 if( reseed_counter_backup != -1 )
287 ctx->reseed_counter = reseed_counter_backup;
288
Andrzej Kurek74f7d0f2020-07-06 14:28:12 -0400289 return MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
290 }
291
Arto Kinnunen5299a422019-11-25 16:19:25 +0200292 if ( ret != 0 )
293 return ret;
294
295 if ( ret == 0 && ctx->reseed_counter == 1 )
296 {
297 /* All ok, return 0 from ret */
298 return ret;
299 }
300
Andrzej Kurekca609372020-07-08 03:19:02 -0400301 /* Rollback the reseed_counter in case of FI */
302 if( reseed_counter_backup != -1 )
303 ctx->reseed_counter = reseed_counter_backup;
Arto Kinnunen5299a422019-11-25 16:19:25 +0200304 return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100305}
306
307/*
Hanno Becker31c95e12019-08-27 09:22:09 +0100308 * HMAC_DRBG reseeding: 10.1.2.4 + 9.2
Hanno Beckereab304c2019-08-26 15:29:14 +0100309 */
310int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
311 const unsigned char *additional, size_t len )
312{
Arto Kinnunen5b366932019-11-20 16:13:13 +0200313 return( hmac_drbg_reseed_core( ctx, additional, len, HMAC_NONCE_NO ) );
Hanno Beckereab304c2019-08-26 15:29:14 +0100314}
315
316/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100317 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
Hanno Becker31c95e12019-08-27 09:22:09 +0100318 *
319 * The nonce is not passed as a separate parameter but extracted
320 * from the entropy source as suggested in 8.6.7.
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100321 */
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200322int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
Hanno Beckera5cedbc2019-07-17 11:21:02 +0100323 mbedtls_md_handle_t md_info,
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100324 int (*f_entropy)(void *, unsigned char *, size_t),
325 void *p_entropy,
326 const unsigned char *custom,
327 size_t len )
328{
Andrzej Kurekfd56f402020-05-25 11:52:05 -0400329 int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
Andrzej Kurek74f7d0f2020-07-06 14:28:12 -0400330 int (* volatile f_entropy_dup)(void *, unsigned char *, size_t) = f_entropy;
331 volatile void *p_entropy_dup = p_entropy;
332 volatile const unsigned char *custom_dup = custom;
333 volatile size_t len_dup = len;
334
Hanno Beckereab304c2019-08-26 15:29:14 +0100335 size_t md_size;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100336
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200337 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100338 return( ret );
339
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200340 md_size = mbedtls_md_get_size( md_info );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100341
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100342 /*
343 * Set initial working state.
344 * Use the V memory location, which is currently all 0, to initialize the
345 * MD context with an all-zero key. Then set V to its initial value.
346 */
Gilles Peskineb7f71c82018-09-11 16:54:57 +0200347 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ) ) != 0 )
348 return( ret );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100349 memset( ctx->V, 0x01, md_size );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100350
351 ctx->f_entropy = f_entropy;
352 ctx->p_entropy = p_entropy;
353
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200354 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100355
Gilles Peskine1d2a9e82019-10-04 11:47:35 +0200356 if( ctx->entropy_len == 0 )
357 {
358 /*
359 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
360 * each hash function, then according to SP800-90A rev1 10.1 table 2,
361 * min_entropy_len (in bits) is security_strength.
362 *
363 * (This also matches the sizes used in the NIST test vectors.)
364 */
365 ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
366 md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
367 32; /* better (256+) -> 256 bits */
368 }
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100369
Arto Kinnunen5b366932019-11-20 16:13:13 +0200370 if( ( ret = hmac_drbg_reseed_core( ctx, custom, len, HMAC_NONCE_YES ) ) != 0 )
Hanno Beckereab304c2019-08-26 15:29:14 +0100371 {
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100372 return( ret );
Hanno Beckereab304c2019-08-26 15:29:14 +0100373 }
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100374
Andrzej Kurek74f7d0f2020-07-06 14:28:12 -0400375 if( f_entropy != f_entropy_dup || p_entropy != p_entropy_dup ||
376 custom_dup != custom || len_dup != len )
377 {
378 ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
379 }
Arto Kinnunen5b366932019-11-20 16:13:13 +0200380 return( ret );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100381}
382
383/*
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100384 * Set prediction resistance
385 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200386void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100387 int resistance )
388{
389 ctx->prediction_resistance = resistance;
390}
391
392/*
Andrzej Kurek4353b692020-07-19 04:58:58 -0400393 * Set the reseeding flag
394 */
395void mbedtls_hmac_drbg_set_reseeding( mbedtls_hmac_drbg_context *ctx,
396 int reseed_flag )
397{
398 ctx->reseed_flag = reseed_flag;
399}
400
401/*
Gilles Peskine1d2a9e82019-10-04 11:47:35 +0200402 * Set entropy length grabbed for seeding
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100403 */
Andrzej Kurek6bc37fa2020-07-18 06:05:03 -0400404int mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100405{
Andrzej Kurek6bc37fa2020-07-18 06:05:03 -0400406 if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
407 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
408
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100409 ctx->entropy_len = len;
Andrzej Kurek6bc37fa2020-07-18 06:05:03 -0400410 return 0;
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100411}
412
413/*
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100414 * Set reseed interval
415 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200416void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval )
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100417{
418 ctx->reseed_interval = interval;
419}
420
421/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100422 * HMAC_DRBG random function with optional additional data:
423 * 10.1.2.5 (arabic) + 9.3 (Roman)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100424 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200425int mbedtls_hmac_drbg_random_with_add( void *p_rng,
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100426 unsigned char *output, size_t out_len,
427 const unsigned char *additional, size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100428{
Andrzej Kurekfd56f402020-05-25 11:52:05 -0400429 int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
Arto Kinnunen5b366932019-11-20 16:13:13 +0200430 volatile unsigned char *output_fi = output;
431 volatile size_t out_len_fi = out_len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200432 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
Hanno Beckerd3827c72019-09-03 12:56:37 +0100433 size_t md_len = mbedtls_md_get_size(
434 mbedtls_md_get_handle( &ctx->md_ctx ) );
Andrzej Kurek9167aa92020-07-18 00:10:50 -0400435 volatile size_t left = out_len;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100436 unsigned char *out = output;
437
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100438 /* II. Check request length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200439 if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST )
440 return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100441
442 /* III. Check input length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200443 if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
444 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100445
446 /* 1. (aka VII and IX) Check reseed counter and PR */
Andrzej Kurek4353b692020-07-19 04:58:58 -0400447 if( ctx->reseed_flag != MBEDTLS_HMAC_DRBG_NO_RESEED &&
448 ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
449 ctx->reseed_counter > ctx->reseed_interval ) )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100450 {
Andrzej Kurek4353b692020-07-19 04:58:58 -0400451 if( ctx->f_entropy == NULL )
452 {
453 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
454 }
455 else
456 {
457 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
458 return( ret );
459 add_len = 0; /* VII.4 */
460 }
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100461 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100462
463 /* 2. Use additional data if any */
464 if( additional != NULL && add_len != 0 )
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200465 {
466 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
467 additional, add_len ) ) != 0 )
468 goto exit;
469 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100470
471 /* 3, 4, 5. Generate bytes */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100472 while( left != 0 )
473 {
474 size_t use_len = left > md_len ? md_len : left;
475
Gilles Peskineb7f71c82018-09-11 16:54:57 +0200476 if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
477 goto exit;
478 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
479 ctx->V, md_len ) ) != 0 )
480 goto exit;
481 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
482 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100483
Teppo Järvelin91d79382019-10-02 09:09:31 +0300484 mbedtls_platform_memcpy( out, ctx->V, use_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100485 out += use_len;
486 left -= use_len;
487 }
488
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100489 /* 6. Update */
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200490 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
491 additional, add_len ) ) != 0 )
492 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100493
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100494 /* 7. Update reseed counter */
495 ctx->reseed_counter++;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100496
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200497exit:
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100498 /* 8. Done */
Arto Kinnunen5b366932019-11-20 16:13:13 +0200499
Arto Kinnunen5299a422019-11-25 16:19:25 +0200500 if ( ret != 0 )
501 return ret;
502
503 /*
504 * Check doubled variables and illegal conditions in case of possible
505 * attack.
506 */
507 if ( ( out_len_fi == out_len ) && ( output_fi == output) &&
508 ( left == 0 ) )
Arto Kinnunen5b366932019-11-20 16:13:13 +0200509 {
Arto Kinnunen5299a422019-11-25 16:19:25 +0200510 return ret; // Success, return 0
Arto Kinnunen5b366932019-11-20 16:13:13 +0200511 }
512
Arto Kinnunen5299a422019-11-25 16:19:25 +0200513 return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100514}
515
516/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100517 * HMAC_DRBG random function
518 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200519int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100520{
Andrzej Kurekfd56f402020-05-25 11:52:05 -0400521 int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100522 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
523
524#if defined(MBEDTLS_THREADING_C)
525 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
526 return( ret );
527#endif
528
529 ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
530
531#if defined(MBEDTLS_THREADING_C)
532 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
533 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
534#endif
535
536 return( ret );
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100537}
538
539/*
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100540 * Free an HMAC_DRBG context
541 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200542void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100543{
544 if( ctx == NULL )
545 return;
546
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100547#if defined(MBEDTLS_THREADING_C)
548 mbedtls_mutex_free( &ctx->mutex );
549#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200550 mbedtls_md_free( &ctx->md_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500551 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100552}
553
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200554#if defined(MBEDTLS_FS_IO)
555int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100556{
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100557 int ret;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100558 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200559 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100560
561 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200562 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100563
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200564 if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100565 goto exit;
566
567 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
568 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200569 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
Paul Bakker4c284c92014-03-26 15:33:05 +0100570 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100571 }
572
573 ret = 0;
574
575exit:
576 fclose( f );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500577 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100578
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100579 return( ret );
580}
581
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200582int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100583{
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100584 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200585 FILE *f = NULL;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100586 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200587 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200588 unsigned char c;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100589
590 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200591 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100592
Gilles Peskine82204662018-09-11 18:43:09 +0200593 n = fread( buf, 1, sizeof( buf ), f );
594 if( fread( &c, 1, 1, f ) != 0 )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100595 {
Gilles Peskine82204662018-09-11 18:43:09 +0200596 ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
597 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100598 }
Gilles Peskine82204662018-09-11 18:43:09 +0200599 if( n == 0 || ferror( f ) )
600 {
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100601 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200602 goto exit;
603 }
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100604 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200605 f = NULL;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100606
Gilles Peskine82204662018-09-11 18:43:09 +0200607 ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n );
608
609exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500610 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200611 if( f != NULL )
612 fclose( f );
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100613 if( ret != 0 )
614 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200615 return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100616}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200617#endif /* MBEDTLS_FS_IO */
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100618
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100619
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200620#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100621
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200622#if !defined(MBEDTLS_SHA1_C)
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100623/* Dummy checkup routine */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200624int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100625{
Manuel Pégourié-Gonnardd1004f02015-08-07 10:46:54 +0200626 (void) verbose;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100627 return( 0 );
628}
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100629#else
630
631#define OUTPUT_LEN 80
632
633/* From a NIST PR=true test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000634static const unsigned char entropy_pr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100635 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
636 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
637 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
638 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
639 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
640static const unsigned char result_pr[OUTPUT_LEN] = {
641 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
642 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
643 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
644 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
645 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
646 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
647 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
648
649/* From a NIST PR=false test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000650static const unsigned char entropy_nopr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100651 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
652 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
653 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
654 0xe9, 0x9d, 0xfe, 0xdf };
655static const unsigned char result_nopr[OUTPUT_LEN] = {
656 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
657 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
658 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
659 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
660 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
661 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
662 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
663
664/* "Entropy" from buffer */
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100665static size_t test_offset;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100666static int hmac_drbg_self_test_entropy( void *data,
667 unsigned char *buf, size_t len )
668{
669 const unsigned char *p = data;
Teppo Järvelinb5c46712019-10-04 13:35:55 +0300670 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100671 test_offset += len;
672 return( 0 );
673}
674
Paul Bakker7dc4c442014-02-01 22:50:26 +0100675#define CHK( c ) if( (c) != 0 ) \
676 { \
677 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200678 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100679 return( 1 ); \
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100680 }
681
682/*
683 * Checkup routine for HMAC_DRBG with SHA-1
684 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200685int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100686{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200687 mbedtls_hmac_drbg_context ctx;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100688 unsigned char buf[OUTPUT_LEN];
Hanno Beckera5cedbc2019-07-17 11:21:02 +0100689 mbedtls_md_handle_t md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100690
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200691 mbedtls_hmac_drbg_init( &ctx );
692
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100693 /*
694 * PR = True
695 */
696 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200697 mbedtls_printf( " HMAC_DRBG (PR = True) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100698
699 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200700 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000701 hmac_drbg_self_test_entropy, (void *) entropy_pr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100702 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200703 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
704 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
705 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100706 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200707 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100708
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100709 mbedtls_hmac_drbg_free( &ctx );
710
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100711 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200712 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100713
714 /*
715 * PR = False
716 */
717 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200718 mbedtls_printf( " HMAC_DRBG (PR = False) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100719
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100720 mbedtls_hmac_drbg_init( &ctx );
721
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100722 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200723 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000724 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100725 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200726 CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
727 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
728 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100729 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200730 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100731
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100732 mbedtls_hmac_drbg_free( &ctx );
733
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100734 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200735 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100736
737 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200738 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100739
740 return( 0 );
741}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200742#endif /* MBEDTLS_SHA1_C */
743#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100744
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200745#endif /* MBEDTLS_HMAC_DRBG_C */