blob: 92d7ba4dd8e26edbf8f7d1a86c3b8e65dff1b0f2 [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 Kurek9167aa92020-07-18 00:10:50 -0400213 const unsigned char * volatile additional_dup = additional;
Andrzej Kurek74f7d0f2020-07-06 14:28:12 -0400214 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 */
Andrzej Kurek6bc37fa2020-07-18 06:05:03 -0400393int mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100394{
Andrzej Kurek6bc37fa2020-07-18 06:05:03 -0400395 if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
396 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
397
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100398 ctx->entropy_len = len;
Andrzej Kurek6bc37fa2020-07-18 06:05:03 -0400399 return 0;
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100400}
401
402/*
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100403 * Set reseed interval
404 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200405void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval )
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100406{
407 ctx->reseed_interval = interval;
408}
409
410/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100411 * HMAC_DRBG random function with optional additional data:
412 * 10.1.2.5 (arabic) + 9.3 (Roman)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100413 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200414int mbedtls_hmac_drbg_random_with_add( void *p_rng,
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100415 unsigned char *output, size_t out_len,
416 const unsigned char *additional, size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100417{
Andrzej Kurekfd56f402020-05-25 11:52:05 -0400418 int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
Arto Kinnunen5b366932019-11-20 16:13:13 +0200419 volatile unsigned char *output_fi = output;
420 volatile size_t out_len_fi = out_len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200421 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
Hanno Beckerd3827c72019-09-03 12:56:37 +0100422 size_t md_len = mbedtls_md_get_size(
423 mbedtls_md_get_handle( &ctx->md_ctx ) );
Andrzej Kurek9167aa92020-07-18 00:10:50 -0400424 volatile size_t left = out_len;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100425 unsigned char *out = output;
426
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100427 /* II. Check request length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200428 if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST )
429 return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100430
431 /* III. Check input length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200432 if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
433 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100434
435 /* 1. (aka VII and IX) Check reseed counter and PR */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100436 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
Andrzej Kurek9167aa92020-07-18 00:10:50 -0400437 ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
438 ctx->reseed_counter > ctx->reseed_interval ) )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100439 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200440 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100441 return( ret );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100442
443 add_len = 0; /* VII.4 */
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100444 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100445
446 /* 2. Use additional data if any */
447 if( additional != NULL && add_len != 0 )
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200448 {
449 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
450 additional, add_len ) ) != 0 )
451 goto exit;
452 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100453
454 /* 3, 4, 5. Generate bytes */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100455 while( left != 0 )
456 {
457 size_t use_len = left > md_len ? md_len : left;
458
Gilles Peskineb7f71c82018-09-11 16:54:57 +0200459 if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
460 goto exit;
461 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
462 ctx->V, md_len ) ) != 0 )
463 goto exit;
464 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
465 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100466
Teppo Järvelin91d79382019-10-02 09:09:31 +0300467 mbedtls_platform_memcpy( out, ctx->V, use_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100468 out += use_len;
469 left -= use_len;
470 }
471
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100472 /* 6. Update */
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200473 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
474 additional, add_len ) ) != 0 )
475 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100476
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100477 /* 7. Update reseed counter */
478 ctx->reseed_counter++;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100479
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200480exit:
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100481 /* 8. Done */
Arto Kinnunen5b366932019-11-20 16:13:13 +0200482
Arto Kinnunen5299a422019-11-25 16:19:25 +0200483 if ( ret != 0 )
484 return ret;
485
486 /*
487 * Check doubled variables and illegal conditions in case of possible
488 * attack.
489 */
490 if ( ( out_len_fi == out_len ) && ( output_fi == output) &&
491 ( left == 0 ) )
Arto Kinnunen5b366932019-11-20 16:13:13 +0200492 {
Arto Kinnunen5299a422019-11-25 16:19:25 +0200493 return ret; // Success, return 0
Arto Kinnunen5b366932019-11-20 16:13:13 +0200494 }
495
Arto Kinnunen5299a422019-11-25 16:19:25 +0200496 return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100497}
498
499/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100500 * HMAC_DRBG random function
501 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200502int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100503{
Andrzej Kurekfd56f402020-05-25 11:52:05 -0400504 int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100505 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
506
507#if defined(MBEDTLS_THREADING_C)
508 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
509 return( ret );
510#endif
511
512 ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
513
514#if defined(MBEDTLS_THREADING_C)
515 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
516 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
517#endif
518
519 return( ret );
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100520}
521
522/*
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100523 * Free an HMAC_DRBG context
524 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200525void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100526{
527 if( ctx == NULL )
528 return;
529
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100530#if defined(MBEDTLS_THREADING_C)
531 mbedtls_mutex_free( &ctx->mutex );
532#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200533 mbedtls_md_free( &ctx->md_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500534 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100535}
536
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200537#if defined(MBEDTLS_FS_IO)
538int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100539{
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100540 int ret;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100541 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200542 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100543
544 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200545 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100546
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200547 if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100548 goto exit;
549
550 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
551 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200552 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
Paul Bakker4c284c92014-03-26 15:33:05 +0100553 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100554 }
555
556 ret = 0;
557
558exit:
559 fclose( f );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500560 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100561
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100562 return( ret );
563}
564
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200565int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100566{
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100567 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200568 FILE *f = NULL;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100569 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200570 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200571 unsigned char c;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100572
573 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200574 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100575
Gilles Peskine82204662018-09-11 18:43:09 +0200576 n = fread( buf, 1, sizeof( buf ), f );
577 if( fread( &c, 1, 1, f ) != 0 )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100578 {
Gilles Peskine82204662018-09-11 18:43:09 +0200579 ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
580 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100581 }
Gilles Peskine82204662018-09-11 18:43:09 +0200582 if( n == 0 || ferror( f ) )
583 {
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100584 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200585 goto exit;
586 }
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100587 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200588 f = NULL;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100589
Gilles Peskine82204662018-09-11 18:43:09 +0200590 ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n );
591
592exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500593 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200594 if( f != NULL )
595 fclose( f );
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100596 if( ret != 0 )
597 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200598 return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100599}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200600#endif /* MBEDTLS_FS_IO */
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100601
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100602
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200603#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100604
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200605#if !defined(MBEDTLS_SHA1_C)
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100606/* Dummy checkup routine */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200607int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100608{
Manuel Pégourié-Gonnardd1004f02015-08-07 10:46:54 +0200609 (void) verbose;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100610 return( 0 );
611}
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100612#else
613
614#define OUTPUT_LEN 80
615
616/* From a NIST PR=true test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000617static const unsigned char entropy_pr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100618 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
619 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
620 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
621 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
622 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
623static const unsigned char result_pr[OUTPUT_LEN] = {
624 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
625 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
626 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
627 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
628 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
629 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
630 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
631
632/* From a NIST PR=false test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000633static const unsigned char entropy_nopr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100634 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
635 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
636 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
637 0xe9, 0x9d, 0xfe, 0xdf };
638static const unsigned char result_nopr[OUTPUT_LEN] = {
639 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
640 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
641 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
642 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
643 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
644 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
645 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
646
647/* "Entropy" from buffer */
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100648static size_t test_offset;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100649static int hmac_drbg_self_test_entropy( void *data,
650 unsigned char *buf, size_t len )
651{
652 const unsigned char *p = data;
Teppo Järvelinb5c46712019-10-04 13:35:55 +0300653 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100654 test_offset += len;
655 return( 0 );
656}
657
Paul Bakker7dc4c442014-02-01 22:50:26 +0100658#define CHK( c ) if( (c) != 0 ) \
659 { \
660 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200661 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100662 return( 1 ); \
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100663 }
664
665/*
666 * Checkup routine for HMAC_DRBG with SHA-1
667 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200668int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100669{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200670 mbedtls_hmac_drbg_context ctx;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100671 unsigned char buf[OUTPUT_LEN];
Hanno Beckera5cedbc2019-07-17 11:21:02 +0100672 mbedtls_md_handle_t md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100673
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200674 mbedtls_hmac_drbg_init( &ctx );
675
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100676 /*
677 * PR = True
678 */
679 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200680 mbedtls_printf( " HMAC_DRBG (PR = True) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100681
682 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200683 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000684 hmac_drbg_self_test_entropy, (void *) entropy_pr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100685 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200686 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
687 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
688 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100689 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200690 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100691
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100692 mbedtls_hmac_drbg_free( &ctx );
693
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100694 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200695 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100696
697 /*
698 * PR = False
699 */
700 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200701 mbedtls_printf( " HMAC_DRBG (PR = False) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100702
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100703 mbedtls_hmac_drbg_init( &ctx );
704
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100705 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200706 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000707 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100708 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200709 CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
710 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
711 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100712 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200713 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100714
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100715 mbedtls_hmac_drbg_free( &ctx );
716
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100717 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200718 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100719
720 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200721 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100722
723 return( 0 );
724}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200725#endif /* MBEDTLS_SHA1_C */
726#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100727
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200728#endif /* MBEDTLS_HMAC_DRBG_C */