blob: 58750c8b7c539d1b422cf0747099f8ab24d3a2af [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;
Andrzej Kurekca609372020-07-08 03:19:02 -0400215 int reseed_counter_backup = -1;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100216
Arto Kinnunen5b366932019-11-20 16:13:13 +0200217 if( use_nonce == HMAC_NONCE_NO )
218 total_entropy_len = ctx->entropy_len;
219 else
220 total_entropy_len = ctx->entropy_len * 3 / 2;
221
222 /* III. Check input length */
223 if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
224 total_entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100225 {
Arto Kinnunen5b366932019-11-20 16:13:13 +0200226 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100227 }
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100228
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200229 memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100230
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100231 /* IV. Gather entropy_len bytes of entropy for the seed */
Gilles Peskineb7f71c82018-09-11 16:54:57 +0200232 if( ( ret = ctx->f_entropy( ctx->p_entropy,
233 seed, ctx->entropy_len ) ) != 0 )
Hanno Beckereab304c2019-08-26 15:29:14 +0100234 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200235 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
Hanno Beckereab304c2019-08-26 15:29:14 +0100236 }
237 seedlen += ctx->entropy_len;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100238
Hanno Becker31c95e12019-08-27 09:22:09 +0100239 /* For initial seeding, allow adding of nonce generated
240 * from the entropy source. See Sect 8.6.7 in SP800-90A. */
Arto Kinnunen5b366932019-11-20 16:13:13 +0200241 if( use_nonce == HMAC_NONCE_YES )
Hanno Beckereab304c2019-08-26 15:29:14 +0100242 {
243 /* Note: We don't merge the two calls to f_entropy() in order
244 * to avoid requesting too much entropy from f_entropy()
245 * at once. Specifically, if the underlying digest is not
246 * SHA-1, 3 / 2 * entropy_len is at least 36 Bytes, which
247 * is larger than the maximum of 32 Bytes that our own
248 * entropy source implementation can emit in a single
249 * call in configurations disabling SHA-512. */
250 if( ( ret = ctx->f_entropy( ctx->p_entropy,
251 seed + seedlen,
252 ctx->entropy_len / 2 ) ) != 0 )
253 {
254 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
255 }
256
257 seedlen += ctx->entropy_len / 2;
258 }
259
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100260
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100261 /* 1. Concatenate entropy and additional data if any */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100262 if( additional != NULL && len != 0 )
263 {
Teppo Järvelin91d79382019-10-02 09:09:31 +0300264 mbedtls_platform_memcpy( seed + seedlen, additional, len );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100265 seedlen += len;
266 }
267
268 /* 2. Update state */
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200269 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, seed, seedlen ) ) != 0 )
270 goto exit;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100271
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100272 /* 3. Reset reseed_counter */
Andrzej Kurekca609372020-07-08 03:19:02 -0400273 reseed_counter_backup = ctx->reseed_counter;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100274 ctx->reseed_counter = 1;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100275
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200276exit:
Arto Kinnunen5299a422019-11-25 16:19:25 +0200277
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100278 /* 4. Done */
Gilles Peskineafa80372018-09-11 15:35:41 +0200279 mbedtls_platform_zeroize( seed, seedlen );
Arto Kinnunen5299a422019-11-25 16:19:25 +0200280
Andrzej Kurek74f7d0f2020-07-06 14:28:12 -0400281 if( additional_dup != additional || len_dup != len )
282 {
Andrzej Kurekca609372020-07-08 03:19:02 -0400283 /* Rollback the reseed_counter in case of FI */
284 if( reseed_counter_backup != -1 )
285 ctx->reseed_counter = reseed_counter_backup;
286
Andrzej Kurek74f7d0f2020-07-06 14:28:12 -0400287 return MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
288 }
289
Arto Kinnunen5299a422019-11-25 16:19:25 +0200290 if ( ret != 0 )
291 return ret;
292
293 if ( ret == 0 && ctx->reseed_counter == 1 )
294 {
295 /* All ok, return 0 from ret */
296 return ret;
297 }
298
Andrzej Kurekca609372020-07-08 03:19:02 -0400299 /* Rollback the reseed_counter in case of FI */
300 if( reseed_counter_backup != -1 )
301 ctx->reseed_counter = reseed_counter_backup;
Arto Kinnunen5299a422019-11-25 16:19:25 +0200302 return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100303}
304
305/*
Hanno Becker31c95e12019-08-27 09:22:09 +0100306 * HMAC_DRBG reseeding: 10.1.2.4 + 9.2
Hanno Beckereab304c2019-08-26 15:29:14 +0100307 */
308int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
309 const unsigned char *additional, size_t len )
310{
Arto Kinnunen5b366932019-11-20 16:13:13 +0200311 return( hmac_drbg_reseed_core( ctx, additional, len, HMAC_NONCE_NO ) );
Hanno Beckereab304c2019-08-26 15:29:14 +0100312}
313
314/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100315 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
Hanno Becker31c95e12019-08-27 09:22:09 +0100316 *
317 * The nonce is not passed as a separate parameter but extracted
318 * from the entropy source as suggested in 8.6.7.
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100319 */
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200320int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
Hanno Beckera5cedbc2019-07-17 11:21:02 +0100321 mbedtls_md_handle_t md_info,
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100322 int (*f_entropy)(void *, unsigned char *, size_t),
323 void *p_entropy,
324 const unsigned char *custom,
325 size_t len )
326{
Andrzej Kurekfd56f402020-05-25 11:52:05 -0400327 int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
Andrzej Kurek74f7d0f2020-07-06 14:28:12 -0400328 int (* volatile f_entropy_dup)(void *, unsigned char *, size_t) = f_entropy;
329 volatile void *p_entropy_dup = p_entropy;
330 volatile const unsigned char *custom_dup = custom;
331 volatile size_t len_dup = len;
332
Hanno Beckereab304c2019-08-26 15:29:14 +0100333 size_t md_size;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100334
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200335 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100336 return( ret );
337
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200338 md_size = mbedtls_md_get_size( md_info );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100339
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100340 /*
341 * Set initial working state.
342 * Use the V memory location, which is currently all 0, to initialize the
343 * MD context with an all-zero key. Then set V to its initial value.
344 */
Gilles Peskineb7f71c82018-09-11 16:54:57 +0200345 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ) ) != 0 )
346 return( ret );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100347 memset( ctx->V, 0x01, md_size );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100348
349 ctx->f_entropy = f_entropy;
350 ctx->p_entropy = p_entropy;
351
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200352 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100353
Gilles Peskine1d2a9e82019-10-04 11:47:35 +0200354 if( ctx->entropy_len == 0 )
355 {
356 /*
357 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
358 * each hash function, then according to SP800-90A rev1 10.1 table 2,
359 * min_entropy_len (in bits) is security_strength.
360 *
361 * (This also matches the sizes used in the NIST test vectors.)
362 */
363 ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
364 md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
365 32; /* better (256+) -> 256 bits */
366 }
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100367
Arto Kinnunen5b366932019-11-20 16:13:13 +0200368 if( ( ret = hmac_drbg_reseed_core( ctx, custom, len, HMAC_NONCE_YES ) ) != 0 )
Hanno Beckereab304c2019-08-26 15:29:14 +0100369 {
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100370 return( ret );
Hanno Beckereab304c2019-08-26 15:29:14 +0100371 }
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100372
Andrzej Kurek74f7d0f2020-07-06 14:28:12 -0400373 if( f_entropy != f_entropy_dup || p_entropy != p_entropy_dup ||
374 custom_dup != custom || len_dup != len )
375 {
376 ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
377 }
Arto Kinnunen5b366932019-11-20 16:13:13 +0200378 return( ret );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100379}
380
381/*
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100382 * Set prediction resistance
383 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200384void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100385 int resistance )
386{
387 ctx->prediction_resistance = resistance;
388}
389
390/*
Gilles Peskine1d2a9e82019-10-04 11:47:35 +0200391 * Set entropy length grabbed for seeding
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100392 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200393void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100394{
395 ctx->entropy_len = len;
396}
397
398/*
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100399 * Set reseed interval
400 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200401void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval )
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100402{
403 ctx->reseed_interval = interval;
404}
405
406/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100407 * HMAC_DRBG random function with optional additional data:
408 * 10.1.2.5 (arabic) + 9.3 (Roman)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100409 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200410int mbedtls_hmac_drbg_random_with_add( void *p_rng,
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100411 unsigned char *output, size_t out_len,
412 const unsigned char *additional, size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100413{
Andrzej Kurekfd56f402020-05-25 11:52:05 -0400414 int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
Arto Kinnunen5b366932019-11-20 16:13:13 +0200415 volatile unsigned char *output_fi = output;
416 volatile size_t out_len_fi = out_len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200417 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
Hanno Beckerd3827c72019-09-03 12:56:37 +0100418 size_t md_len = mbedtls_md_get_size(
419 mbedtls_md_get_handle( &ctx->md_ctx ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100420 size_t left = out_len;
421 unsigned char *out = output;
422
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100423 /* II. Check request length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200424 if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST )
425 return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100426
427 /* III. Check input length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200428 if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
429 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100430
431 /* 1. (aka VII and IX) Check reseed counter and PR */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100432 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200433 ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100434 ctx->reseed_counter > ctx->reseed_interval ) )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100435 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200436 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100437 return( ret );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100438
439 add_len = 0; /* VII.4 */
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100440 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100441
442 /* 2. Use additional data if any */
443 if( additional != NULL && add_len != 0 )
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200444 {
445 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
446 additional, add_len ) ) != 0 )
447 goto exit;
448 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100449
450 /* 3, 4, 5. Generate bytes */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100451 while( left != 0 )
452 {
453 size_t use_len = left > md_len ? md_len : left;
454
Gilles Peskineb7f71c82018-09-11 16:54:57 +0200455 if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
456 goto exit;
457 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
458 ctx->V, md_len ) ) != 0 )
459 goto exit;
460 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
461 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100462
Teppo Järvelin91d79382019-10-02 09:09:31 +0300463 mbedtls_platform_memcpy( out, ctx->V, use_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100464 out += use_len;
465 left -= use_len;
466 }
467
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100468 /* 6. Update */
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200469 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
470 additional, add_len ) ) != 0 )
471 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100472
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100473 /* 7. Update reseed counter */
474 ctx->reseed_counter++;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100475
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200476exit:
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100477 /* 8. Done */
Arto Kinnunen5b366932019-11-20 16:13:13 +0200478
Arto Kinnunen5299a422019-11-25 16:19:25 +0200479 if ( ret != 0 )
480 return ret;
481
482 /*
483 * Check doubled variables and illegal conditions in case of possible
484 * attack.
485 */
486 if ( ( out_len_fi == out_len ) && ( output_fi == output) &&
487 ( left == 0 ) )
Arto Kinnunen5b366932019-11-20 16:13:13 +0200488 {
Arto Kinnunen5299a422019-11-25 16:19:25 +0200489 return ret; // Success, return 0
Arto Kinnunen5b366932019-11-20 16:13:13 +0200490 }
491
Arto Kinnunen5299a422019-11-25 16:19:25 +0200492 return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100493}
494
495/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100496 * HMAC_DRBG random function
497 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200498int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100499{
Andrzej Kurekfd56f402020-05-25 11:52:05 -0400500 int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100501 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
502
503#if defined(MBEDTLS_THREADING_C)
504 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
505 return( ret );
506#endif
507
508 ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
509
510#if defined(MBEDTLS_THREADING_C)
511 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
512 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
513#endif
514
515 return( ret );
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100516}
517
518/*
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100519 * Free an HMAC_DRBG context
520 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200521void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100522{
523 if( ctx == NULL )
524 return;
525
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100526#if defined(MBEDTLS_THREADING_C)
527 mbedtls_mutex_free( &ctx->mutex );
528#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200529 mbedtls_md_free( &ctx->md_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500530 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100531}
532
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200533#if defined(MBEDTLS_FS_IO)
534int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100535{
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100536 int ret;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100537 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200538 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100539
540 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200541 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100542
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200543 if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100544 goto exit;
545
546 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
547 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200548 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
Paul Bakker4c284c92014-03-26 15:33:05 +0100549 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100550 }
551
552 ret = 0;
553
554exit:
555 fclose( f );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500556 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100557
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100558 return( ret );
559}
560
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200561int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100562{
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100563 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200564 FILE *f = NULL;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100565 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200566 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200567 unsigned char c;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100568
569 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200570 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100571
Gilles Peskine82204662018-09-11 18:43:09 +0200572 n = fread( buf, 1, sizeof( buf ), f );
573 if( fread( &c, 1, 1, f ) != 0 )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100574 {
Gilles Peskine82204662018-09-11 18:43:09 +0200575 ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
576 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100577 }
Gilles Peskine82204662018-09-11 18:43:09 +0200578 if( n == 0 || ferror( f ) )
579 {
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100580 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200581 goto exit;
582 }
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100583 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200584 f = NULL;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100585
Gilles Peskine82204662018-09-11 18:43:09 +0200586 ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n );
587
588exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500589 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200590 if( f != NULL )
591 fclose( f );
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100592 if( ret != 0 )
593 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200594 return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100595}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200596#endif /* MBEDTLS_FS_IO */
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100597
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100598
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200599#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100600
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200601#if !defined(MBEDTLS_SHA1_C)
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100602/* Dummy checkup routine */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200603int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100604{
Manuel Pégourié-Gonnardd1004f02015-08-07 10:46:54 +0200605 (void) verbose;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100606 return( 0 );
607}
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100608#else
609
610#define OUTPUT_LEN 80
611
612/* From a NIST PR=true test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000613static const unsigned char entropy_pr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100614 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
615 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
616 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
617 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
618 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
619static const unsigned char result_pr[OUTPUT_LEN] = {
620 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
621 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
622 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
623 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
624 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
625 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
626 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
627
628/* From a NIST PR=false test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000629static const unsigned char entropy_nopr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100630 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
631 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
632 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
633 0xe9, 0x9d, 0xfe, 0xdf };
634static const unsigned char result_nopr[OUTPUT_LEN] = {
635 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
636 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
637 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
638 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
639 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
640 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
641 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
642
643/* "Entropy" from buffer */
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100644static size_t test_offset;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100645static int hmac_drbg_self_test_entropy( void *data,
646 unsigned char *buf, size_t len )
647{
648 const unsigned char *p = data;
Teppo Järvelinb5c46712019-10-04 13:35:55 +0300649 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100650 test_offset += len;
651 return( 0 );
652}
653
Paul Bakker7dc4c442014-02-01 22:50:26 +0100654#define CHK( c ) if( (c) != 0 ) \
655 { \
656 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200657 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100658 return( 1 ); \
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100659 }
660
661/*
662 * Checkup routine for HMAC_DRBG with SHA-1
663 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200664int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100665{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200666 mbedtls_hmac_drbg_context ctx;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100667 unsigned char buf[OUTPUT_LEN];
Hanno Beckera5cedbc2019-07-17 11:21:02 +0100668 mbedtls_md_handle_t md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100669
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200670 mbedtls_hmac_drbg_init( &ctx );
671
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100672 /*
673 * PR = True
674 */
675 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200676 mbedtls_printf( " HMAC_DRBG (PR = True) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100677
678 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200679 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000680 hmac_drbg_self_test_entropy, (void *) entropy_pr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100681 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200682 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
683 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
684 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100685 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200686 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100687
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100688 mbedtls_hmac_drbg_free( &ctx );
689
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100690 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200691 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100692
693 /*
694 * PR = False
695 */
696 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200697 mbedtls_printf( " HMAC_DRBG (PR = False) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100698
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100699 mbedtls_hmac_drbg_init( &ctx );
700
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100701 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200702 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000703 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100704 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200705 CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
706 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
707 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100708 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200709 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100710
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100711 mbedtls_hmac_drbg_free( &ctx );
712
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100713 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200714 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100715
716 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200717 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100718
719 return( 0 );
720}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200721#endif /* MBEDTLS_SHA1_C */
722#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100723
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200724#endif /* MBEDTLS_HMAC_DRBG_C */