blob: 90174d5d17d56324ed14029b8f58431b98b99848 [file] [log] [blame]
Jens Wiklander817466c2018-05-22 13:49:31 +02001/*
2 * HMAC_DRBG implementation (NIST SP 800-90)
3 *
Jerome Forissier79013242021-07-28 10:24:04 +02004 * Copyright The Mbed TLS Contributors
Tom Van Eyckc1633172024-04-09 18:44:13 +02005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Jens Wiklander817466c2018-05-22 13:49:31 +02006 */
7
8/*
9 * The NIST SP 800-90A DRBGs are described in the following publication.
10 * http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
11 * References below are based on rev. 1 (January 2012).
12 */
13
Jerome Forissier79013242021-07-28 10:24:04 +020014#include "common.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020015
16#if defined(MBEDTLS_HMAC_DRBG_C)
17
18#include "mbedtls/hmac_drbg.h"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010019#include "mbedtls/platform_util.h"
Jerome Forissier11fa71b2020-04-20 17:17:56 +020020#include "mbedtls/error.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020021
22#include <string.h>
23
24#if defined(MBEDTLS_FS_IO)
25#include <stdio.h>
26#endif
27
Jens Wiklander817466c2018-05-22 13:49:31 +020028#include "mbedtls/platform.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020029
Jens Wiklander817466c2018-05-22 13:49:31 +020030/*
31 * HMAC_DRBG context initialization
32 */
Jens Wiklander32b31802023-10-06 16:59:46 +020033void mbedtls_hmac_drbg_init(mbedtls_hmac_drbg_context *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +020034{
Jens Wiklander32b31802023-10-06 16:59:46 +020035 memset(ctx, 0, sizeof(mbedtls_hmac_drbg_context));
Jens Wiklander817466c2018-05-22 13:49:31 +020036
Jerome Forissier79013242021-07-28 10:24:04 +020037 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
Jens Wiklander817466c2018-05-22 13:49:31 +020038}
39
40/*
41 * HMAC_DRBG update, using optional additional data (10.1.2.2)
42 */
Jens Wiklander32b31802023-10-06 16:59:46 +020043int mbedtls_hmac_drbg_update(mbedtls_hmac_drbg_context *ctx,
44 const unsigned char *additional,
45 size_t add_len)
Jens Wiklander817466c2018-05-22 13:49:31 +020046{
Jens Wiklander32b31802023-10-06 16:59:46 +020047 size_t md_len = mbedtls_md_get_size(ctx->md_ctx.md_info);
48 unsigned char rounds = (additional != NULL && add_len != 0) ? 2 : 1;
Jens Wiklander817466c2018-05-22 13:49:31 +020049 unsigned char sep[1];
50 unsigned char K[MBEDTLS_MD_MAX_SIZE];
Jerome Forissier11fa71b2020-04-20 17:17:56 +020051 int ret = MBEDTLS_ERR_MD_BAD_INPUT_DATA;
Jens Wiklander817466c2018-05-22 13:49:31 +020052
Jens Wiklander32b31802023-10-06 16:59:46 +020053 for (sep[0] = 0; sep[0] < rounds; sep[0]++) {
Jens Wiklander817466c2018-05-22 13:49:31 +020054 /* Step 1 or 4 */
Jens Wiklander32b31802023-10-06 16:59:46 +020055 if ((ret = mbedtls_md_hmac_reset(&ctx->md_ctx)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +010056 goto exit;
57 }
Jens Wiklander32b31802023-10-06 16:59:46 +020058 if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,
59 ctx->V, md_len)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +010060 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +020061 }
62 if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,
63 sep, 1)) != 0) {
64 goto exit;
65 }
66 if (rounds == 2) {
67 if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,
68 additional, add_len)) != 0) {
69 goto exit;
70 }
71 }
72 if ((ret = mbedtls_md_hmac_finish(&ctx->md_ctx, K)) != 0) {
73 goto exit;
74 }
Jens Wiklander817466c2018-05-22 13:49:31 +020075
76 /* Step 2 or 5 */
Jens Wiklander32b31802023-10-06 16:59:46 +020077 if ((ret = mbedtls_md_hmac_starts(&ctx->md_ctx, K, md_len)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +010078 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +020079 }
80 if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,
81 ctx->V, md_len)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +010082 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +020083 }
84 if ((ret = mbedtls_md_hmac_finish(&ctx->md_ctx, ctx->V)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +010085 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +020086 }
Jens Wiklander817466c2018-05-22 13:49:31 +020087 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +010088
89exit:
Jens Wiklander32b31802023-10-06 16:59:46 +020090 mbedtls_platform_zeroize(K, sizeof(K));
91 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +020092}
93
94/*
95 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
96 */
Jens Wiklander32b31802023-10-06 16:59:46 +020097int mbedtls_hmac_drbg_seed_buf(mbedtls_hmac_drbg_context *ctx,
98 const mbedtls_md_info_t *md_info,
99 const unsigned char *data, size_t data_len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200100{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200101 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200102
Jens Wiklander32b31802023-10-06 16:59:46 +0200103 if ((ret = mbedtls_md_setup(&ctx->md_ctx, md_info, 1)) != 0) {
104 return ret;
105 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200106
Jerome Forissier79013242021-07-28 10:24:04 +0200107#if defined(MBEDTLS_THREADING_C)
Jens Wiklander32b31802023-10-06 16:59:46 +0200108 mbedtls_mutex_init(&ctx->mutex);
Jerome Forissier79013242021-07-28 10:24:04 +0200109#endif
110
Jens Wiklander817466c2018-05-22 13:49:31 +0200111 /*
112 * Set initial working state.
113 * Use the V memory location, which is currently all 0, to initialize the
114 * MD context with an all-zero key. Then set V to its initial value.
115 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200116 if ((ret = mbedtls_md_hmac_starts(&ctx->md_ctx, ctx->V,
117 mbedtls_md_get_size(md_info))) != 0) {
118 return ret;
119 }
120 memset(ctx->V, 0x01, mbedtls_md_get_size(md_info));
Jens Wiklander817466c2018-05-22 13:49:31 +0200121
Jens Wiklander32b31802023-10-06 16:59:46 +0200122 if ((ret = mbedtls_hmac_drbg_update(ctx, data, data_len)) != 0) {
123 return ret;
124 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200125
Jens Wiklander32b31802023-10-06 16:59:46 +0200126 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200127}
128
129/*
Jerome Forissier5b25c762020-04-07 11:18:49 +0200130 * Internal function used both for seeding and reseeding the DRBG.
131 * Comments starting with arabic numbers refer to section 10.1.2.4
132 * of SP800-90A, while roman numbers refer to section 9.2.
Jens Wiklander817466c2018-05-22 13:49:31 +0200133 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200134static int hmac_drbg_reseed_core(mbedtls_hmac_drbg_context *ctx,
135 const unsigned char *additional, size_t len,
136 int use_nonce)
Jens Wiklander817466c2018-05-22 13:49:31 +0200137{
138 unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
Jerome Forissier5b25c762020-04-07 11:18:49 +0200139 size_t seedlen = 0;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200140 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200141
Jens Wiklander817466c2018-05-22 13:49:31 +0200142 {
Jerome Forissier5b25c762020-04-07 11:18:49 +0200143 size_t total_entropy_len;
144
Jens Wiklander32b31802023-10-06 16:59:46 +0200145 if (use_nonce == 0) {
Jerome Forissier5b25c762020-04-07 11:18:49 +0200146 total_entropy_len = ctx->entropy_len;
Jens Wiklander32b31802023-10-06 16:59:46 +0200147 } else {
Jerome Forissier5b25c762020-04-07 11:18:49 +0200148 total_entropy_len = ctx->entropy_len * 3 / 2;
Jens Wiklander32b31802023-10-06 16:59:46 +0200149 }
Jerome Forissier5b25c762020-04-07 11:18:49 +0200150
151 /* III. Check input length */
Jens Wiklander32b31802023-10-06 16:59:46 +0200152 if (len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
153 total_entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT) {
154 return MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200155 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200156 }
157
Jens Wiklander32b31802023-10-06 16:59:46 +0200158 memset(seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT);
Jens Wiklander817466c2018-05-22 13:49:31 +0200159
160 /* IV. Gather entropy_len bytes of entropy for the seed */
Jens Wiklander32b31802023-10-06 16:59:46 +0200161 if ((ret = ctx->f_entropy(ctx->p_entropy,
162 seed, ctx->entropy_len)) != 0) {
163 return MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200164 }
165 seedlen += ctx->entropy_len;
Jens Wiklander817466c2018-05-22 13:49:31 +0200166
Jerome Forissier5b25c762020-04-07 11:18:49 +0200167 /* For initial seeding, allow adding of nonce generated
168 * from the entropy source. See Sect 8.6.7 in SP800-90A. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200169 if (use_nonce) {
Jerome Forissier5b25c762020-04-07 11:18:49 +0200170 /* Note: We don't merge the two calls to f_entropy() in order
171 * to avoid requesting too much entropy from f_entropy()
172 * at once. Specifically, if the underlying digest is not
173 * SHA-1, 3 / 2 * entropy_len is at least 36 Bytes, which
174 * is larger than the maximum of 32 Bytes that our own
175 * entropy source implementation can emit in a single
176 * call in configurations disabling SHA-512. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200177 if ((ret = ctx->f_entropy(ctx->p_entropy,
178 seed + seedlen,
179 ctx->entropy_len / 2)) != 0) {
180 return MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200181 }
182
183 seedlen += ctx->entropy_len / 2;
184 }
185
Jens Wiklander817466c2018-05-22 13:49:31 +0200186
187 /* 1. Concatenate entropy and additional data if any */
Jens Wiklander32b31802023-10-06 16:59:46 +0200188 if (additional != NULL && len != 0) {
189 memcpy(seed + seedlen, additional, len);
Jens Wiklander817466c2018-05-22 13:49:31 +0200190 seedlen += len;
191 }
192
193 /* 2. Update state */
Jens Wiklander32b31802023-10-06 16:59:46 +0200194 if ((ret = mbedtls_hmac_drbg_update(ctx, seed, seedlen)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100195 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200196 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200197
198 /* 3. Reset reseed_counter */
199 ctx->reseed_counter = 1;
200
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100201exit:
Jens Wiklander817466c2018-05-22 13:49:31 +0200202 /* 4. Done */
Jens Wiklander32b31802023-10-06 16:59:46 +0200203 mbedtls_platform_zeroize(seed, seedlen);
204 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200205}
206
207/*
Jerome Forissier5b25c762020-04-07 11:18:49 +0200208 * HMAC_DRBG reseeding: 10.1.2.4 + 9.2
209 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200210int mbedtls_hmac_drbg_reseed(mbedtls_hmac_drbg_context *ctx,
211 const unsigned char *additional, size_t len)
Jerome Forissier5b25c762020-04-07 11:18:49 +0200212{
Jens Wiklander32b31802023-10-06 16:59:46 +0200213 return hmac_drbg_reseed_core(ctx, additional, len, 0);
Jerome Forissier5b25c762020-04-07 11:18:49 +0200214}
215
216/*
Jens Wiklander817466c2018-05-22 13:49:31 +0200217 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
Jerome Forissier5b25c762020-04-07 11:18:49 +0200218 *
219 * The nonce is not passed as a separate parameter but extracted
220 * from the entropy source as suggested in 8.6.7.
Jens Wiklander817466c2018-05-22 13:49:31 +0200221 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200222int mbedtls_hmac_drbg_seed(mbedtls_hmac_drbg_context *ctx,
223 const mbedtls_md_info_t *md_info,
224 int (*f_entropy)(void *, unsigned char *, size_t),
225 void *p_entropy,
226 const unsigned char *custom,
227 size_t len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200228{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200229 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200230 size_t md_size;
Jens Wiklander817466c2018-05-22 13:49:31 +0200231
Jens Wiklander32b31802023-10-06 16:59:46 +0200232 if ((ret = mbedtls_md_setup(&ctx->md_ctx, md_info, 1)) != 0) {
233 return ret;
234 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200235
Jerome Forissier79013242021-07-28 10:24:04 +0200236 /* The mutex is initialized iff the md context is set up. */
237#if defined(MBEDTLS_THREADING_C)
Jens Wiklander32b31802023-10-06 16:59:46 +0200238 mbedtls_mutex_init(&ctx->mutex);
Jerome Forissier79013242021-07-28 10:24:04 +0200239#endif
240
Jens Wiklander32b31802023-10-06 16:59:46 +0200241 md_size = mbedtls_md_get_size(md_info);
Jens Wiklander817466c2018-05-22 13:49:31 +0200242
243 /*
244 * Set initial working state.
245 * Use the V memory location, which is currently all 0, to initialize the
246 * MD context with an all-zero key. Then set V to its initial value.
247 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200248 if ((ret = mbedtls_md_hmac_starts(&ctx->md_ctx, ctx->V, md_size)) != 0) {
249 return ret;
250 }
251 memset(ctx->V, 0x01, md_size);
Jens Wiklander817466c2018-05-22 13:49:31 +0200252
253 ctx->f_entropy = f_entropy;
254 ctx->p_entropy = p_entropy;
255
Jens Wiklander32b31802023-10-06 16:59:46 +0200256 if (ctx->entropy_len == 0) {
Jerome Forissier5b25c762020-04-07 11:18:49 +0200257 /*
258 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
259 * each hash function, then according to SP800-90A rev1 10.1 table 2,
260 * min_entropy_len (in bits) is security_strength.
261 *
262 * (This also matches the sizes used in the NIST test vectors.)
263 */
264 ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
265 md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
266 32; /* better (256+) -> 256 bits */
267 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200268
Jens Wiklander32b31802023-10-06 16:59:46 +0200269 if ((ret = hmac_drbg_reseed_core(ctx, custom, len,
270 1 /* add nonce */)) != 0) {
271 return ret;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200272 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200273
Jens Wiklander32b31802023-10-06 16:59:46 +0200274 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200275}
276
277/*
278 * Set prediction resistance
279 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200280void mbedtls_hmac_drbg_set_prediction_resistance(mbedtls_hmac_drbg_context *ctx,
281 int resistance)
Jens Wiklander817466c2018-05-22 13:49:31 +0200282{
283 ctx->prediction_resistance = resistance;
284}
285
286/*
Jerome Forissier5b25c762020-04-07 11:18:49 +0200287 * Set entropy length grabbed for seeding
Jens Wiklander817466c2018-05-22 13:49:31 +0200288 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200289void mbedtls_hmac_drbg_set_entropy_len(mbedtls_hmac_drbg_context *ctx, size_t len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200290{
291 ctx->entropy_len = len;
292}
293
294/*
295 * Set reseed interval
296 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200297void mbedtls_hmac_drbg_set_reseed_interval(mbedtls_hmac_drbg_context *ctx, int interval)
Jens Wiklander817466c2018-05-22 13:49:31 +0200298{
299 ctx->reseed_interval = interval;
300}
301
302/*
303 * HMAC_DRBG random function with optional additional data:
304 * 10.1.2.5 (arabic) + 9.3 (Roman)
305 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200306int mbedtls_hmac_drbg_random_with_add(void *p_rng,
307 unsigned char *output, size_t out_len,
308 const unsigned char *additional, size_t add_len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200309{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200310 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200311 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
Jens Wiklander32b31802023-10-06 16:59:46 +0200312 size_t md_len = mbedtls_md_get_size(ctx->md_ctx.md_info);
Jens Wiklander817466c2018-05-22 13:49:31 +0200313 size_t left = out_len;
314 unsigned char *out = output;
315
316 /* II. Check request length */
Jens Wiklander32b31802023-10-06 16:59:46 +0200317 if (out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST) {
318 return MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG;
319 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200320
321 /* III. Check input length */
Jens Wiklander32b31802023-10-06 16:59:46 +0200322 if (add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT) {
323 return MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
324 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200325
326 /* 1. (aka VII and IX) Check reseed counter and PR */
Jens Wiklander32b31802023-10-06 16:59:46 +0200327 if (ctx->f_entropy != NULL && /* For no-reseeding instances */
328 (ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
329 ctx->reseed_counter > ctx->reseed_interval)) {
330 if ((ret = mbedtls_hmac_drbg_reseed(ctx, additional, add_len)) != 0) {
331 return ret;
332 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200333
334 add_len = 0; /* VII.4 */
335 }
336
337 /* 2. Use additional data if any */
Jens Wiklander32b31802023-10-06 16:59:46 +0200338 if (additional != NULL && add_len != 0) {
339 if ((ret = mbedtls_hmac_drbg_update(ctx,
340 additional, add_len)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100341 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200342 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100343 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200344
345 /* 3, 4, 5. Generate bytes */
Jens Wiklander32b31802023-10-06 16:59:46 +0200346 while (left != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200347 size_t use_len = left > md_len ? md_len : left;
348
Jens Wiklander32b31802023-10-06 16:59:46 +0200349 if ((ret = mbedtls_md_hmac_reset(&ctx->md_ctx)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100350 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200351 }
352 if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,
353 ctx->V, md_len)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100354 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200355 }
356 if ((ret = mbedtls_md_hmac_finish(&ctx->md_ctx, ctx->V)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100357 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200358 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200359
Jens Wiklander32b31802023-10-06 16:59:46 +0200360 memcpy(out, ctx->V, use_len);
Jens Wiklander817466c2018-05-22 13:49:31 +0200361 out += use_len;
362 left -= use_len;
363 }
364
365 /* 6. Update */
Jens Wiklander32b31802023-10-06 16:59:46 +0200366 if ((ret = mbedtls_hmac_drbg_update(ctx,
367 additional, add_len)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100368 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200369 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200370
371 /* 7. Update reseed counter */
372 ctx->reseed_counter++;
373
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100374exit:
Jens Wiklander817466c2018-05-22 13:49:31 +0200375 /* 8. Done */
Jens Wiklander32b31802023-10-06 16:59:46 +0200376 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200377}
378
379/*
380 * HMAC_DRBG random function
381 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200382int mbedtls_hmac_drbg_random(void *p_rng, unsigned char *output, size_t out_len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200383{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200384 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200385 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
386
387#if defined(MBEDTLS_THREADING_C)
Jens Wiklander32b31802023-10-06 16:59:46 +0200388 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
389 return ret;
390 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200391#endif
392
Jens Wiklander32b31802023-10-06 16:59:46 +0200393 ret = mbedtls_hmac_drbg_random_with_add(ctx, output, out_len, NULL, 0);
Jens Wiklander817466c2018-05-22 13:49:31 +0200394
395#if defined(MBEDTLS_THREADING_C)
Jens Wiklander32b31802023-10-06 16:59:46 +0200396 if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
397 return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
398 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200399#endif
400
Jens Wiklander32b31802023-10-06 16:59:46 +0200401 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200402}
403
404/*
Jerome Forissier79013242021-07-28 10:24:04 +0200405 * This function resets HMAC_DRBG context to the state immediately
406 * after initial call of mbedtls_hmac_drbg_init().
Jens Wiklander817466c2018-05-22 13:49:31 +0200407 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200408void mbedtls_hmac_drbg_free(mbedtls_hmac_drbg_context *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +0200409{
Jens Wiklander32b31802023-10-06 16:59:46 +0200410 if (ctx == NULL) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200411 return;
Jens Wiklander32b31802023-10-06 16:59:46 +0200412 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200413
414#if defined(MBEDTLS_THREADING_C)
Jerome Forissier79013242021-07-28 10:24:04 +0200415 /* The mutex is initialized iff the md context is set up. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200416 if (ctx->md_ctx.md_info != NULL) {
417 mbedtls_mutex_free(&ctx->mutex);
418 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200419#endif
Jens Wiklander32b31802023-10-06 16:59:46 +0200420 mbedtls_md_free(&ctx->md_ctx);
421 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_hmac_drbg_context));
Jerome Forissier79013242021-07-28 10:24:04 +0200422 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200423}
424
425#if defined(MBEDTLS_FS_IO)
Jens Wiklander32b31802023-10-06 16:59:46 +0200426int mbedtls_hmac_drbg_write_seed_file(mbedtls_hmac_drbg_context *ctx, const char *path)
Jens Wiklander817466c2018-05-22 13:49:31 +0200427{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200428 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200429 FILE *f;
Jens Wiklander32b31802023-10-06 16:59:46 +0200430 unsigned char buf[MBEDTLS_HMAC_DRBG_MAX_INPUT];
Jens Wiklander817466c2018-05-22 13:49:31 +0200431
Jens Wiklander32b31802023-10-06 16:59:46 +0200432 if ((f = fopen(path, "wb")) == NULL) {
433 return MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
434 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200435
Jens Wiklander32b31802023-10-06 16:59:46 +0200436 /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
437 mbedtls_setbuf(f, NULL);
438
439 if ((ret = mbedtls_hmac_drbg_random(ctx, buf, sizeof(buf))) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200440 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200441 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200442
Jens Wiklander32b31802023-10-06 16:59:46 +0200443 if (fwrite(buf, 1, sizeof(buf), f) != sizeof(buf)) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200444 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
445 goto exit;
446 }
447
448 ret = 0;
449
450exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200451 fclose(f);
452 mbedtls_platform_zeroize(buf, sizeof(buf));
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100453
Jens Wiklander32b31802023-10-06 16:59:46 +0200454 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200455}
456
Jens Wiklander32b31802023-10-06 16:59:46 +0200457int mbedtls_hmac_drbg_update_seed_file(mbedtls_hmac_drbg_context *ctx, const char *path)
Jens Wiklander817466c2018-05-22 13:49:31 +0200458{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100459 int ret = 0;
460 FILE *f = NULL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200461 size_t n;
Jens Wiklander32b31802023-10-06 16:59:46 +0200462 unsigned char buf[MBEDTLS_HMAC_DRBG_MAX_INPUT];
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100463 unsigned char c;
Jens Wiklander817466c2018-05-22 13:49:31 +0200464
Jens Wiklander32b31802023-10-06 16:59:46 +0200465 if ((f = fopen(path, "rb")) == NULL) {
466 return MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
467 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200468
Jens Wiklander32b31802023-10-06 16:59:46 +0200469 /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
470 mbedtls_setbuf(f, NULL);
471
472 n = fread(buf, 1, sizeof(buf), f);
473 if (fread(&c, 1, 1, f) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100474 ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
475 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200476 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200477 if (n == 0 || ferror(f)) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100478 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
479 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200480 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200481 fclose(f);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100482 f = NULL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200483
Jens Wiklander32b31802023-10-06 16:59:46 +0200484 ret = mbedtls_hmac_drbg_update(ctx, buf, n);
Jens Wiklander817466c2018-05-22 13:49:31 +0200485
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100486exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200487 mbedtls_platform_zeroize(buf, sizeof(buf));
488 if (f != NULL) {
489 fclose(f);
490 }
491 if (ret != 0) {
492 return ret;
493 }
494 return mbedtls_hmac_drbg_write_seed_file(ctx, path);
Jens Wiklander817466c2018-05-22 13:49:31 +0200495}
496#endif /* MBEDTLS_FS_IO */
497
498
499#if defined(MBEDTLS_SELF_TEST)
500
Tom Van Eyckc1633172024-04-09 18:44:13 +0200501#if !defined(MBEDTLS_MD_CAN_SHA1)
Jens Wiklander817466c2018-05-22 13:49:31 +0200502/* Dummy checkup routine */
Jens Wiklander32b31802023-10-06 16:59:46 +0200503int mbedtls_hmac_drbg_self_test(int verbose)
Jens Wiklander817466c2018-05-22 13:49:31 +0200504{
505 (void) verbose;
Jens Wiklander32b31802023-10-06 16:59:46 +0200506 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200507}
508#else
509
510#define OUTPUT_LEN 80
511
512/* From a NIST PR=true test vector */
513static const unsigned char entropy_pr[] = {
514 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
515 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
516 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
517 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
Jens Wiklander32b31802023-10-06 16:59:46 +0200518 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4
519};
Jens Wiklander817466c2018-05-22 13:49:31 +0200520static const unsigned char result_pr[OUTPUT_LEN] = {
521 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
522 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
523 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
524 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
525 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
526 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
Jens Wiklander32b31802023-10-06 16:59:46 +0200527 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44
528};
Jens Wiklander817466c2018-05-22 13:49:31 +0200529
530/* From a NIST PR=false test vector */
531static const unsigned char entropy_nopr[] = {
532 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
533 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
534 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
Jens Wiklander32b31802023-10-06 16:59:46 +0200535 0xe9, 0x9d, 0xfe, 0xdf
536};
Jens Wiklander817466c2018-05-22 13:49:31 +0200537static const unsigned char result_nopr[OUTPUT_LEN] = {
538 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
539 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
540 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
541 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
542 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
543 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
Jens Wiklander32b31802023-10-06 16:59:46 +0200544 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7
545};
Jens Wiklander817466c2018-05-22 13:49:31 +0200546
547/* "Entropy" from buffer */
548static size_t test_offset;
Jens Wiklander32b31802023-10-06 16:59:46 +0200549static int hmac_drbg_self_test_entropy(void *data,
550 unsigned char *buf, size_t len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200551{
552 const unsigned char *p = data;
Jens Wiklander32b31802023-10-06 16:59:46 +0200553 memcpy(buf, p + test_offset, len);
Jens Wiklander817466c2018-05-22 13:49:31 +0200554 test_offset += len;
Jens Wiklander32b31802023-10-06 16:59:46 +0200555 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200556}
557
Jens Wiklander32b31802023-10-06 16:59:46 +0200558#define CHK(c) if ((c) != 0) \
559 { \
560 if (verbose != 0) \
561 mbedtls_printf("failed\n"); \
562 return 1; \
563 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200564
565/*
566 * Checkup routine for HMAC_DRBG with SHA-1
567 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200568int mbedtls_hmac_drbg_self_test(int verbose)
Jens Wiklander817466c2018-05-22 13:49:31 +0200569{
570 mbedtls_hmac_drbg_context ctx;
571 unsigned char buf[OUTPUT_LEN];
Jens Wiklander32b31802023-10-06 16:59:46 +0200572 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
Jens Wiklander817466c2018-05-22 13:49:31 +0200573
Jens Wiklander32b31802023-10-06 16:59:46 +0200574 mbedtls_hmac_drbg_init(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200575
576 /*
577 * PR = True
578 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200579 if (verbose != 0) {
580 mbedtls_printf(" HMAC_DRBG (PR = True) : ");
581 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200582
583 test_offset = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +0200584 CHK(mbedtls_hmac_drbg_seed(&ctx, md_info,
585 hmac_drbg_self_test_entropy, (void *) entropy_pr,
586 NULL, 0));
587 mbedtls_hmac_drbg_set_prediction_resistance(&ctx, MBEDTLS_HMAC_DRBG_PR_ON);
588 CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));
589 CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));
590 CHK(memcmp(buf, result_pr, OUTPUT_LEN));
591 mbedtls_hmac_drbg_free(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200592
Jens Wiklander32b31802023-10-06 16:59:46 +0200593 mbedtls_hmac_drbg_free(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200594
Jens Wiklander32b31802023-10-06 16:59:46 +0200595 if (verbose != 0) {
596 mbedtls_printf("passed\n");
597 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200598
599 /*
600 * PR = False
601 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200602 if (verbose != 0) {
603 mbedtls_printf(" HMAC_DRBG (PR = False) : ");
604 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200605
Jens Wiklander32b31802023-10-06 16:59:46 +0200606 mbedtls_hmac_drbg_init(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200607
608 test_offset = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +0200609 CHK(mbedtls_hmac_drbg_seed(&ctx, md_info,
610 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
611 NULL, 0));
612 CHK(mbedtls_hmac_drbg_reseed(&ctx, NULL, 0));
613 CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));
614 CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));
615 CHK(memcmp(buf, result_nopr, OUTPUT_LEN));
616 mbedtls_hmac_drbg_free(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200617
Jens Wiklander32b31802023-10-06 16:59:46 +0200618 mbedtls_hmac_drbg_free(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200619
Jens Wiklander32b31802023-10-06 16:59:46 +0200620 if (verbose != 0) {
621 mbedtls_printf("passed\n");
622 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200623
Jens Wiklander32b31802023-10-06 16:59:46 +0200624 if (verbose != 0) {
625 mbedtls_printf("\n");
626 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200627
Jens Wiklander32b31802023-10-06 16:59:46 +0200628 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200629}
Tom Van Eyckc1633172024-04-09 18:44:13 +0200630#endif /* MBEDTLS_MD_CAN_SHA1 */
Jens Wiklander817466c2018-05-22 13:49:31 +0200631#endif /* MBEDTLS_SELF_TEST */
632
633#endif /* MBEDTLS_HMAC_DRBG_C */