blob: fc7aea9b502b15262228b15aad223c587cc02006 [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;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010066#if defined(MBEDTLS_THREADING_C)
67 mbedtls_mutex_init( &ctx->mutex );
68#endif
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +020069}
70
71/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010072 * HMAC_DRBG update, using optional additional data (10.1.2.2)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010073 */
Gilles Peskinee0e9c572018-09-11 16:47:16 +020074int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx,
75 const unsigned char *additional,
76 size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010077{
Hanno Beckerd3827c72019-09-03 12:56:37 +010078 size_t md_len = mbedtls_md_get_size(
79 mbedtls_md_get_handle( &ctx->md_ctx ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010080 unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
81 unsigned char sep[1];
Arto Kinnunenec37a892019-11-28 13:40:32 +020082 volatile unsigned int flow_counter = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020083 unsigned char K[MBEDTLS_MD_MAX_SIZE];
Arto Kinnunen5b366932019-11-20 16:13:13 +020084 int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
Andrzej Kurek74f7d0f2020-07-06 14:28:12 -040085 volatile const unsigned char *additional_dup = additional;
86 volatile size_t add_len_dup = add_len;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010087
88 for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
89 {
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010090 /* Step 1 or 4 */
Arto Kinnunen5b366932019-11-20 16:13:13 +020091 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +020092 if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
93 goto exit;
Arto Kinnunen5b366932019-11-20 16:13:13 +020094
95 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +020096 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
97 ctx->V, md_len ) ) != 0 )
98 goto exit;
Arto Kinnunen5b366932019-11-20 16:13:13 +020099
100 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200101 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
102 sep, 1 ) ) != 0 )
103 goto exit;
Arto Kinnunen5b366932019-11-20 16:13:13 +0200104
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100105 if( rounds == 2 )
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200106 {
Arto Kinnunen5b366932019-11-20 16:13:13 +0200107 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200108 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
109 additional, add_len ) ) != 0 )
110 goto exit;
111 }
Arto Kinnunen5b366932019-11-20 16:13:13 +0200112
113 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200114 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, K ) ) != 0 )
115 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100116
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100117 /* Step 2 or 5 */
Arto Kinnunen5b366932019-11-20 16:13:13 +0200118 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200119 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ) ) != 0 )
120 goto exit;
Arto Kinnunen5b366932019-11-20 16:13:13 +0200121
122 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200123 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
124 ctx->V, md_len ) ) != 0 )
125 goto exit;
Arto Kinnunen5b366932019-11-20 16:13:13 +0200126
127 flow_counter++;
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200128 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
129 goto exit;
Arto Kinnunen5299a422019-11-25 16:19:25 +0200130 flow_counter++;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100131 }
Gilles Peskineafa80372018-09-11 15:35:41 +0200132
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200133exit:
Arto Kinnunen5b366932019-11-20 16:13:13 +0200134
Arto Kinnunen5299a422019-11-25 16:19:25 +0200135 mbedtls_platform_zeroize( K, sizeof( K ) );
136 /* Check for possible attack.
137 * Counters needs to have correct values when returning success
138 */
139 if ( ret != 0 )
140 return( ret ); // error case, return immediately
141
142 if ( ( ( flow_counter == 8 ) && ( sep[0] == 1 ) ) ||
143 ( ( flow_counter == 18 ) && ( sep[0] == 2 ) ) )
Arto Kinnunen5b366932019-11-20 16:13:13 +0200144 {
Arto Kinnunen5299a422019-11-25 16:19:25 +0200145 flow_counter = flow_counter - sep[0];
146 // Double check flow_counter
147 if ( ( flow_counter == 7 ) || ( flow_counter == 16 ) )
Arto Kinnunen5b366932019-11-20 16:13:13 +0200148 {
Andrzej Kurek74f7d0f2020-07-06 14:28:12 -0400149 if( additional_dup == additional && add_len_dup == add_len )
150 {
151 return ret; // success, return 0 from ret
152 }
Arto Kinnunen5b366932019-11-20 16:13:13 +0200153 }
154 }
155
Arto Kinnunen5299a422019-11-25 16:19:25 +0200156 return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100157}
158
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200159#if !defined(MBEDTLS_DEPRECATED_REMOVED)
160void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
161 const unsigned char *additional,
162 size_t add_len )
163{
164 (void) mbedtls_hmac_drbg_update_ret( ctx, additional, add_len );
165}
166#endif /* MBEDTLS_DEPRECATED_REMOVED */
167
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100168/*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100169 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100170 */
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200171int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
Arto Kinnunen5b366932019-11-20 16:13:13 +0200172 mbedtls_md_handle_t md_info,
173 const unsigned char *data, size_t data_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100174{
Arto Kinnunen5b366932019-11-20 16:13:13 +0200175 int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
Andrzej Kurek74f7d0f2020-07-06 14:28:12 -0400176 volatile const unsigned char *data_dup = data;
177 volatile size_t data_len_dup = data_len;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100178
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200179 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100180 return( ret );
181
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100182 /*
183 * Set initial working state.
184 * Use the V memory location, which is currently all 0, to initialize the
185 * MD context with an all-zero key. Then set V to its initial value.
186 */
Gilles Peskineb7f71c82018-09-11 16:54:57 +0200187 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V,
188 mbedtls_md_get_size( md_info ) ) ) != 0 )
189 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200190 memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100191
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200192 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, data, data_len ) ) != 0 )
193 return( ret );
Andrzej Kurek74f7d0f2020-07-06 14:28:12 -0400194 if( data_dup != data || data_len_dup != data_len )
195 {
196 ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
197 }
Arto Kinnunen5b366932019-11-20 16:13:13 +0200198 return( ret );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100199}
200
Hanno Becker31c95e12019-08-27 09:22:09 +0100201/*
202 * Internal function used both for seeding and reseeding the DRBG.
203 * Comments starting with arabic numbers refer to section 10.1.2.4
204 * of SP800-90A, while roman numbers refer to section 9.2.
205 */
Hanno Beckerb3a06e62019-08-27 09:21:44 +0100206static int hmac_drbg_reseed_core( mbedtls_hmac_drbg_context *ctx,
207 const unsigned char *additional, size_t len,
208 int use_nonce )
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100209{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200210 unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
Hanno Beckereab304c2019-08-26 15:29:14 +0100211 size_t seedlen = 0;
Arto Kinnunen5b366932019-11-20 16:13:13 +0200212 size_t total_entropy_len;
Andrzej Kurekfd56f402020-05-25 11:52:05 -0400213 int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
Andrzej Kurek9167aa92020-07-18 00:10:50 -0400214 const unsigned char * volatile additional_dup = additional;
Andrzej Kurek74f7d0f2020-07-06 14:28:12 -0400215 volatile size_t len_dup = len;
Andrzej Kurekca609372020-07-08 03:19:02 -0400216 int reseed_counter_backup = -1;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100217
Arto Kinnunen5b366932019-11-20 16:13:13 +0200218 if( use_nonce == HMAC_NONCE_NO )
219 total_entropy_len = ctx->entropy_len;
220 else
221 total_entropy_len = ctx->entropy_len * 3 / 2;
222
223 /* III. Check input length */
224 if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
225 total_entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100226 {
Arto Kinnunen5b366932019-11-20 16:13:13 +0200227 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100228 }
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100229
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200230 memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100231
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100232 /* IV. Gather entropy_len bytes of entropy for the seed */
Gilles Peskineb7f71c82018-09-11 16:54:57 +0200233 if( ( ret = ctx->f_entropy( ctx->p_entropy,
234 seed, ctx->entropy_len ) ) != 0 )
Hanno Beckereab304c2019-08-26 15:29:14 +0100235 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200236 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
Hanno Beckereab304c2019-08-26 15:29:14 +0100237 }
238 seedlen += ctx->entropy_len;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100239
Hanno Becker31c95e12019-08-27 09:22:09 +0100240 /* For initial seeding, allow adding of nonce generated
241 * from the entropy source. See Sect 8.6.7 in SP800-90A. */
Arto Kinnunen5b366932019-11-20 16:13:13 +0200242 if( use_nonce == HMAC_NONCE_YES )
Hanno Beckereab304c2019-08-26 15:29:14 +0100243 {
244 /* Note: We don't merge the two calls to f_entropy() in order
245 * to avoid requesting too much entropy from f_entropy()
246 * at once. Specifically, if the underlying digest is not
247 * SHA-1, 3 / 2 * entropy_len is at least 36 Bytes, which
248 * is larger than the maximum of 32 Bytes that our own
249 * entropy source implementation can emit in a single
250 * call in configurations disabling SHA-512. */
251 if( ( ret = ctx->f_entropy( ctx->p_entropy,
252 seed + seedlen,
253 ctx->entropy_len / 2 ) ) != 0 )
254 {
255 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
256 }
257
258 seedlen += ctx->entropy_len / 2;
259 }
260
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100261
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100262 /* 1. Concatenate entropy and additional data if any */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100263 if( additional != NULL && len != 0 )
264 {
Teppo Järvelin91d79382019-10-02 09:09:31 +0300265 mbedtls_platform_memcpy( seed + seedlen, additional, len );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100266 seedlen += len;
267 }
268
269 /* 2. Update state */
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200270 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, seed, seedlen ) ) != 0 )
271 goto exit;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100272
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100273 /* 3. Reset reseed_counter */
Andrzej Kurekca609372020-07-08 03:19:02 -0400274 reseed_counter_backup = ctx->reseed_counter;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100275 ctx->reseed_counter = 1;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100276
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200277exit:
Arto Kinnunen5299a422019-11-25 16:19:25 +0200278
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100279 /* 4. Done */
Gilles Peskineafa80372018-09-11 15:35:41 +0200280 mbedtls_platform_zeroize( seed, seedlen );
Arto Kinnunen5299a422019-11-25 16:19:25 +0200281
Andrzej Kurek74f7d0f2020-07-06 14:28:12 -0400282 if( additional_dup != additional || len_dup != len )
283 {
Andrzej Kurekca609372020-07-08 03:19:02 -0400284 /* Rollback the reseed_counter in case of FI */
285 if( reseed_counter_backup != -1 )
286 ctx->reseed_counter = reseed_counter_backup;
287
Andrzej Kurek74f7d0f2020-07-06 14:28:12 -0400288 return MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
289 }
290
Arto Kinnunen5299a422019-11-25 16:19:25 +0200291 if ( ret != 0 )
292 return ret;
293
294 if ( ret == 0 && ctx->reseed_counter == 1 )
295 {
296 /* All ok, return 0 from ret */
297 return ret;
298 }
299
Andrzej Kurekca609372020-07-08 03:19:02 -0400300 /* Rollback the reseed_counter in case of FI */
301 if( reseed_counter_backup != -1 )
302 ctx->reseed_counter = reseed_counter_backup;
Arto Kinnunen5299a422019-11-25 16:19:25 +0200303 return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100304}
305
306/*
Hanno Becker31c95e12019-08-27 09:22:09 +0100307 * HMAC_DRBG reseeding: 10.1.2.4 + 9.2
Hanno Beckereab304c2019-08-26 15:29:14 +0100308 */
309int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
310 const unsigned char *additional, size_t len )
311{
Arto Kinnunen5b366932019-11-20 16:13:13 +0200312 return( hmac_drbg_reseed_core( ctx, additional, len, HMAC_NONCE_NO ) );
Hanno Beckereab304c2019-08-26 15:29:14 +0100313}
314
315/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100316 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
Hanno Becker31c95e12019-08-27 09:22:09 +0100317 *
318 * The nonce is not passed as a separate parameter but extracted
319 * from the entropy source as suggested in 8.6.7.
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100320 */
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200321int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
Hanno Beckera5cedbc2019-07-17 11:21:02 +0100322 mbedtls_md_handle_t md_info,
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100323 int (*f_entropy)(void *, unsigned char *, size_t),
324 void *p_entropy,
325 const unsigned char *custom,
326 size_t len )
327{
Andrzej Kurekfd56f402020-05-25 11:52:05 -0400328 int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
Andrzej Kurek74f7d0f2020-07-06 14:28:12 -0400329 int (* volatile f_entropy_dup)(void *, unsigned char *, size_t) = f_entropy;
330 volatile void *p_entropy_dup = p_entropy;
331 volatile const unsigned char *custom_dup = custom;
332 volatile size_t len_dup = len;
333
Hanno Beckereab304c2019-08-26 15:29:14 +0100334 size_t md_size;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100335
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200336 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100337 return( ret );
338
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200339 md_size = mbedtls_md_get_size( md_info );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100340
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100341 /*
342 * Set initial working state.
343 * Use the V memory location, which is currently all 0, to initialize the
344 * MD context with an all-zero key. Then set V to its initial value.
345 */
Gilles Peskineb7f71c82018-09-11 16:54:57 +0200346 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ) ) != 0 )
347 return( ret );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100348 memset( ctx->V, 0x01, md_size );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100349
350 ctx->f_entropy = f_entropy;
351 ctx->p_entropy = p_entropy;
352
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200353 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100354
Gilles Peskine1d2a9e82019-10-04 11:47:35 +0200355 if( ctx->entropy_len == 0 )
356 {
357 /*
358 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
359 * each hash function, then according to SP800-90A rev1 10.1 table 2,
360 * min_entropy_len (in bits) is security_strength.
361 *
362 * (This also matches the sizes used in the NIST test vectors.)
363 */
364 ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
365 md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
366 32; /* better (256+) -> 256 bits */
367 }
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100368
Arto Kinnunen5b366932019-11-20 16:13:13 +0200369 if( ( ret = hmac_drbg_reseed_core( ctx, custom, len, HMAC_NONCE_YES ) ) != 0 )
Hanno Beckereab304c2019-08-26 15:29:14 +0100370 {
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100371 return( ret );
Hanno Beckereab304c2019-08-26 15:29:14 +0100372 }
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100373
Andrzej Kurek74f7d0f2020-07-06 14:28:12 -0400374 if( f_entropy != f_entropy_dup || p_entropy != p_entropy_dup ||
375 custom_dup != custom || len_dup != len )
376 {
377 ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
378 }
Arto Kinnunen5b366932019-11-20 16:13:13 +0200379 return( ret );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100380}
381
382/*
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100383 * Set prediction resistance
384 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200385void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100386 int resistance )
387{
388 ctx->prediction_resistance = resistance;
389}
390
391/*
Gilles Peskine1d2a9e82019-10-04 11:47:35 +0200392 * Set entropy length grabbed for seeding
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100393 */
Andrzej Kurek6bc37fa2020-07-18 06:05:03 -0400394int mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100395{
Andrzej Kurek6bc37fa2020-07-18 06:05:03 -0400396 if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
397 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
398
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100399 ctx->entropy_len = len;
Andrzej Kurek6bc37fa2020-07-18 06:05:03 -0400400 return 0;
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100401}
402
403/*
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100404 * Set reseed interval
405 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200406void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval )
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100407{
408 ctx->reseed_interval = interval;
409}
410
411/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100412 * HMAC_DRBG random function with optional additional data:
413 * 10.1.2.5 (arabic) + 9.3 (Roman)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100414 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200415int mbedtls_hmac_drbg_random_with_add( void *p_rng,
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100416 unsigned char *output, size_t out_len,
417 const unsigned char *additional, size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100418{
Andrzej Kurekfd56f402020-05-25 11:52:05 -0400419 int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
Arto Kinnunen5b366932019-11-20 16:13:13 +0200420 volatile unsigned char *output_fi = output;
421 volatile size_t out_len_fi = out_len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200422 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
Hanno Beckerd3827c72019-09-03 12:56:37 +0100423 size_t md_len = mbedtls_md_get_size(
424 mbedtls_md_get_handle( &ctx->md_ctx ) );
Andrzej Kurek9167aa92020-07-18 00:10:50 -0400425 volatile size_t left = out_len;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100426 unsigned char *out = output;
427
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100428 /* II. Check request length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200429 if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST )
430 return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100431
432 /* III. Check input length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200433 if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
434 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100435
436 /* 1. (aka VII and IX) Check reseed counter and PR */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100437 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
Andrzej Kurek9167aa92020-07-18 00:10:50 -0400438 ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
439 ctx->reseed_counter > ctx->reseed_interval ) )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100440 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200441 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100442 return( ret );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100443
444 add_len = 0; /* VII.4 */
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100445 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100446
447 /* 2. Use additional data if any */
448 if( additional != NULL && add_len != 0 )
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200449 {
450 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
451 additional, add_len ) ) != 0 )
452 goto exit;
453 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100454
455 /* 3, 4, 5. Generate bytes */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100456 while( left != 0 )
457 {
458 size_t use_len = left > md_len ? md_len : left;
459
Gilles Peskineb7f71c82018-09-11 16:54:57 +0200460 if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
461 goto exit;
462 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
463 ctx->V, md_len ) ) != 0 )
464 goto exit;
465 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
466 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100467
Teppo Järvelin91d79382019-10-02 09:09:31 +0300468 mbedtls_platform_memcpy( out, ctx->V, use_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100469 out += use_len;
470 left -= use_len;
471 }
472
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100473 /* 6. Update */
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200474 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
475 additional, add_len ) ) != 0 )
476 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100477
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100478 /* 7. Update reseed counter */
479 ctx->reseed_counter++;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100480
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200481exit:
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100482 /* 8. Done */
Arto Kinnunen5b366932019-11-20 16:13:13 +0200483
Arto Kinnunen5299a422019-11-25 16:19:25 +0200484 if ( ret != 0 )
485 return ret;
486
487 /*
488 * Check doubled variables and illegal conditions in case of possible
489 * attack.
490 */
491 if ( ( out_len_fi == out_len ) && ( output_fi == output) &&
492 ( left == 0 ) )
Arto Kinnunen5b366932019-11-20 16:13:13 +0200493 {
Arto Kinnunen5299a422019-11-25 16:19:25 +0200494 return ret; // Success, return 0
Arto Kinnunen5b366932019-11-20 16:13:13 +0200495 }
496
Arto Kinnunen5299a422019-11-25 16:19:25 +0200497 return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100498}
499
500/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100501 * HMAC_DRBG random function
502 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200503int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100504{
Andrzej Kurekfd56f402020-05-25 11:52:05 -0400505 int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100506 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
507
508#if defined(MBEDTLS_THREADING_C)
509 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
510 return( ret );
511#endif
512
513 ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
514
515#if defined(MBEDTLS_THREADING_C)
516 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
517 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
518#endif
519
520 return( ret );
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100521}
522
523/*
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100524 * Free an HMAC_DRBG context
525 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200526void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100527{
528 if( ctx == NULL )
529 return;
530
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100531#if defined(MBEDTLS_THREADING_C)
532 mbedtls_mutex_free( &ctx->mutex );
533#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200534 mbedtls_md_free( &ctx->md_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500535 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100536}
537
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200538#if defined(MBEDTLS_FS_IO)
539int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100540{
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100541 int ret;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100542 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200543 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100544
545 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200546 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100547
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200548 if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100549 goto exit;
550
551 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
552 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200553 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
Paul Bakker4c284c92014-03-26 15:33:05 +0100554 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100555 }
556
557 ret = 0;
558
559exit:
560 fclose( f );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500561 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100562
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100563 return( ret );
564}
565
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200566int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100567{
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100568 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200569 FILE *f = NULL;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100570 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200571 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200572 unsigned char c;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100573
574 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200575 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100576
Gilles Peskine82204662018-09-11 18:43:09 +0200577 n = fread( buf, 1, sizeof( buf ), f );
578 if( fread( &c, 1, 1, f ) != 0 )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100579 {
Gilles Peskine82204662018-09-11 18:43:09 +0200580 ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
581 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100582 }
Gilles Peskine82204662018-09-11 18:43:09 +0200583 if( n == 0 || ferror( f ) )
584 {
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100585 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200586 goto exit;
587 }
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100588 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200589 f = NULL;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100590
Gilles Peskine82204662018-09-11 18:43:09 +0200591 ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n );
592
593exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500594 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200595 if( f != NULL )
596 fclose( f );
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100597 if( ret != 0 )
598 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200599 return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100600}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200601#endif /* MBEDTLS_FS_IO */
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100602
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100603
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200604#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100605
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200606#if !defined(MBEDTLS_SHA1_C)
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100607/* Dummy checkup routine */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200608int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100609{
Manuel Pégourié-Gonnardd1004f02015-08-07 10:46:54 +0200610 (void) verbose;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100611 return( 0 );
612}
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100613#else
614
615#define OUTPUT_LEN 80
616
617/* From a NIST PR=true test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000618static const unsigned char entropy_pr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100619 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
620 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
621 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
622 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
623 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
624static const unsigned char result_pr[OUTPUT_LEN] = {
625 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
626 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
627 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
628 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
629 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
630 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
631 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
632
633/* From a NIST PR=false test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000634static const unsigned char entropy_nopr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100635 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
636 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
637 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
638 0xe9, 0x9d, 0xfe, 0xdf };
639static const unsigned char result_nopr[OUTPUT_LEN] = {
640 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
641 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
642 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
643 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
644 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
645 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
646 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
647
648/* "Entropy" from buffer */
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100649static size_t test_offset;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100650static int hmac_drbg_self_test_entropy( void *data,
651 unsigned char *buf, size_t len )
652{
653 const unsigned char *p = data;
Teppo Järvelinb5c46712019-10-04 13:35:55 +0300654 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100655 test_offset += len;
656 return( 0 );
657}
658
Paul Bakker7dc4c442014-02-01 22:50:26 +0100659#define CHK( c ) if( (c) != 0 ) \
660 { \
661 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200662 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100663 return( 1 ); \
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100664 }
665
666/*
667 * Checkup routine for HMAC_DRBG with SHA-1
668 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200669int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100670{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200671 mbedtls_hmac_drbg_context ctx;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100672 unsigned char buf[OUTPUT_LEN];
Hanno Beckera5cedbc2019-07-17 11:21:02 +0100673 mbedtls_md_handle_t md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100674
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200675 mbedtls_hmac_drbg_init( &ctx );
676
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100677 /*
678 * PR = True
679 */
680 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200681 mbedtls_printf( " HMAC_DRBG (PR = True) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100682
683 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200684 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000685 hmac_drbg_self_test_entropy, (void *) entropy_pr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100686 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200687 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
688 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
689 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100690 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200691 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100692
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100693 mbedtls_hmac_drbg_free( &ctx );
694
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100695 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200696 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100697
698 /*
699 * PR = False
700 */
701 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200702 mbedtls_printf( " HMAC_DRBG (PR = False) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100703
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100704 mbedtls_hmac_drbg_init( &ctx );
705
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100706 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200707 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000708 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100709 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200710 CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
711 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
712 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100713 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200714 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100715
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100716 mbedtls_hmac_drbg_free( &ctx );
717
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100718 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200719 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100720
721 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200722 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100723
724 return( 0 );
725}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200726#endif /* MBEDTLS_SHA1_C */
727#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100728
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200729#endif /* MBEDTLS_HMAC_DRBG_C */