blob: b15730235c309fb1306d21eeefe018c87217f5d2 [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
5 * SPDX-License-Identifier: Apache-2.0
Jens Wiklander817466c2018-05-22 13:49:31 +02006 *
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.
Jens Wiklander817466c2018-05-22 13:49:31 +020018 */
19
20/*
21 * The NIST SP 800-90A DRBGs are described in the following publication.
22 * http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
23 * References below are based on rev. 1 (January 2012).
24 */
25
Jerome Forissier79013242021-07-28 10:24:04 +020026#include "common.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020027
28#if defined(MBEDTLS_HMAC_DRBG_C)
29
30#include "mbedtls/hmac_drbg.h"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010031#include "mbedtls/platform_util.h"
Jerome Forissier11fa71b2020-04-20 17:17:56 +020032#include "mbedtls/error.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020033
34#include <string.h>
35
36#if defined(MBEDTLS_FS_IO)
37#include <stdio.h>
38#endif
39
Jens Wiklander817466c2018-05-22 13:49:31 +020040#include "mbedtls/platform.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020041
Jens Wiklander817466c2018-05-22 13:49:31 +020042/*
43 * HMAC_DRBG context initialization
44 */
Jens Wiklander32b31802023-10-06 16:59:46 +020045void mbedtls_hmac_drbg_init(mbedtls_hmac_drbg_context *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +020046{
Jens Wiklander32b31802023-10-06 16:59:46 +020047 memset(ctx, 0, sizeof(mbedtls_hmac_drbg_context));
Jens Wiklander817466c2018-05-22 13:49:31 +020048
Jerome Forissier79013242021-07-28 10:24:04 +020049 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
Jens Wiklander817466c2018-05-22 13:49:31 +020050}
51
52/*
53 * HMAC_DRBG update, using optional additional data (10.1.2.2)
54 */
Jens Wiklander32b31802023-10-06 16:59:46 +020055int mbedtls_hmac_drbg_update(mbedtls_hmac_drbg_context *ctx,
56 const unsigned char *additional,
57 size_t add_len)
Jens Wiklander817466c2018-05-22 13:49:31 +020058{
Jens Wiklander32b31802023-10-06 16:59:46 +020059 size_t md_len = mbedtls_md_get_size(ctx->md_ctx.md_info);
60 unsigned char rounds = (additional != NULL && add_len != 0) ? 2 : 1;
Jens Wiklander817466c2018-05-22 13:49:31 +020061 unsigned char sep[1];
62 unsigned char K[MBEDTLS_MD_MAX_SIZE];
Jerome Forissier11fa71b2020-04-20 17:17:56 +020063 int ret = MBEDTLS_ERR_MD_BAD_INPUT_DATA;
Jens Wiklander817466c2018-05-22 13:49:31 +020064
Jens Wiklander32b31802023-10-06 16:59:46 +020065 for (sep[0] = 0; sep[0] < rounds; sep[0]++) {
Jens Wiklander817466c2018-05-22 13:49:31 +020066 /* Step 1 or 4 */
Jens Wiklander32b31802023-10-06 16:59:46 +020067 if ((ret = mbedtls_md_hmac_reset(&ctx->md_ctx)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +010068 goto exit;
69 }
Jens Wiklander32b31802023-10-06 16:59:46 +020070 if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,
71 ctx->V, md_len)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +010072 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +020073 }
74 if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,
75 sep, 1)) != 0) {
76 goto exit;
77 }
78 if (rounds == 2) {
79 if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,
80 additional, add_len)) != 0) {
81 goto exit;
82 }
83 }
84 if ((ret = mbedtls_md_hmac_finish(&ctx->md_ctx, K)) != 0) {
85 goto exit;
86 }
Jens Wiklander817466c2018-05-22 13:49:31 +020087
88 /* Step 2 or 5 */
Jens Wiklander32b31802023-10-06 16:59:46 +020089 if ((ret = mbedtls_md_hmac_starts(&ctx->md_ctx, K, md_len)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +010090 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +020091 }
92 if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,
93 ctx->V, md_len)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +010094 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +020095 }
96 if ((ret = mbedtls_md_hmac_finish(&ctx->md_ctx, ctx->V)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +010097 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +020098 }
Jens Wiklander817466c2018-05-22 13:49:31 +020099 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100100
101exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200102 mbedtls_platform_zeroize(K, sizeof(K));
103 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200104}
105
106/*
107 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
108 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200109int mbedtls_hmac_drbg_seed_buf(mbedtls_hmac_drbg_context *ctx,
110 const mbedtls_md_info_t *md_info,
111 const unsigned char *data, size_t data_len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200112{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200113 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200114
Jens Wiklander32b31802023-10-06 16:59:46 +0200115 if ((ret = mbedtls_md_setup(&ctx->md_ctx, md_info, 1)) != 0) {
116 return ret;
117 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200118
Jerome Forissier79013242021-07-28 10:24:04 +0200119#if defined(MBEDTLS_THREADING_C)
Jens Wiklander32b31802023-10-06 16:59:46 +0200120 mbedtls_mutex_init(&ctx->mutex);
Jerome Forissier79013242021-07-28 10:24:04 +0200121#endif
122
Jens Wiklander817466c2018-05-22 13:49:31 +0200123 /*
124 * Set initial working state.
125 * Use the V memory location, which is currently all 0, to initialize the
126 * MD context with an all-zero key. Then set V to its initial value.
127 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200128 if ((ret = mbedtls_md_hmac_starts(&ctx->md_ctx, ctx->V,
129 mbedtls_md_get_size(md_info))) != 0) {
130 return ret;
131 }
132 memset(ctx->V, 0x01, mbedtls_md_get_size(md_info));
Jens Wiklander817466c2018-05-22 13:49:31 +0200133
Jens Wiklander32b31802023-10-06 16:59:46 +0200134 if ((ret = mbedtls_hmac_drbg_update(ctx, data, data_len)) != 0) {
135 return ret;
136 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200137
Jens Wiklander32b31802023-10-06 16:59:46 +0200138 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200139}
140
141/*
Jerome Forissier5b25c762020-04-07 11:18:49 +0200142 * Internal function used both for seeding and reseeding the DRBG.
143 * Comments starting with arabic numbers refer to section 10.1.2.4
144 * of SP800-90A, while roman numbers refer to section 9.2.
Jens Wiklander817466c2018-05-22 13:49:31 +0200145 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200146static int hmac_drbg_reseed_core(mbedtls_hmac_drbg_context *ctx,
147 const unsigned char *additional, size_t len,
148 int use_nonce)
Jens Wiklander817466c2018-05-22 13:49:31 +0200149{
150 unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
Jerome Forissier5b25c762020-04-07 11:18:49 +0200151 size_t seedlen = 0;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200152 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200153
Jens Wiklander817466c2018-05-22 13:49:31 +0200154 {
Jerome Forissier5b25c762020-04-07 11:18:49 +0200155 size_t total_entropy_len;
156
Jens Wiklander32b31802023-10-06 16:59:46 +0200157 if (use_nonce == 0) {
Jerome Forissier5b25c762020-04-07 11:18:49 +0200158 total_entropy_len = ctx->entropy_len;
Jens Wiklander32b31802023-10-06 16:59:46 +0200159 } else {
Jerome Forissier5b25c762020-04-07 11:18:49 +0200160 total_entropy_len = ctx->entropy_len * 3 / 2;
Jens Wiklander32b31802023-10-06 16:59:46 +0200161 }
Jerome Forissier5b25c762020-04-07 11:18:49 +0200162
163 /* III. Check input length */
Jens Wiklander32b31802023-10-06 16:59:46 +0200164 if (len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
165 total_entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT) {
166 return MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200167 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200168 }
169
Jens Wiklander32b31802023-10-06 16:59:46 +0200170 memset(seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT);
Jens Wiklander817466c2018-05-22 13:49:31 +0200171
172 /* IV. Gather entropy_len bytes of entropy for the seed */
Jens Wiklander32b31802023-10-06 16:59:46 +0200173 if ((ret = ctx->f_entropy(ctx->p_entropy,
174 seed, ctx->entropy_len)) != 0) {
175 return MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200176 }
177 seedlen += ctx->entropy_len;
Jens Wiklander817466c2018-05-22 13:49:31 +0200178
Jerome Forissier5b25c762020-04-07 11:18:49 +0200179 /* For initial seeding, allow adding of nonce generated
180 * from the entropy source. See Sect 8.6.7 in SP800-90A. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200181 if (use_nonce) {
Jerome Forissier5b25c762020-04-07 11:18:49 +0200182 /* Note: We don't merge the two calls to f_entropy() in order
183 * to avoid requesting too much entropy from f_entropy()
184 * at once. Specifically, if the underlying digest is not
185 * SHA-1, 3 / 2 * entropy_len is at least 36 Bytes, which
186 * is larger than the maximum of 32 Bytes that our own
187 * entropy source implementation can emit in a single
188 * call in configurations disabling SHA-512. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200189 if ((ret = ctx->f_entropy(ctx->p_entropy,
190 seed + seedlen,
191 ctx->entropy_len / 2)) != 0) {
192 return MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200193 }
194
195 seedlen += ctx->entropy_len / 2;
196 }
197
Jens Wiklander817466c2018-05-22 13:49:31 +0200198
199 /* 1. Concatenate entropy and additional data if any */
Jens Wiklander32b31802023-10-06 16:59:46 +0200200 if (additional != NULL && len != 0) {
201 memcpy(seed + seedlen, additional, len);
Jens Wiklander817466c2018-05-22 13:49:31 +0200202 seedlen += len;
203 }
204
205 /* 2. Update state */
Jens Wiklander32b31802023-10-06 16:59:46 +0200206 if ((ret = mbedtls_hmac_drbg_update(ctx, seed, seedlen)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100207 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200208 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200209
210 /* 3. Reset reseed_counter */
211 ctx->reseed_counter = 1;
212
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100213exit:
Jens Wiklander817466c2018-05-22 13:49:31 +0200214 /* 4. Done */
Jens Wiklander32b31802023-10-06 16:59:46 +0200215 mbedtls_platform_zeroize(seed, seedlen);
216 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200217}
218
219/*
Jerome Forissier5b25c762020-04-07 11:18:49 +0200220 * HMAC_DRBG reseeding: 10.1.2.4 + 9.2
221 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200222int mbedtls_hmac_drbg_reseed(mbedtls_hmac_drbg_context *ctx,
223 const unsigned char *additional, size_t len)
Jerome Forissier5b25c762020-04-07 11:18:49 +0200224{
Jens Wiklander32b31802023-10-06 16:59:46 +0200225 return hmac_drbg_reseed_core(ctx, additional, len, 0);
Jerome Forissier5b25c762020-04-07 11:18:49 +0200226}
227
228/*
Jens Wiklander817466c2018-05-22 13:49:31 +0200229 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
Jerome Forissier5b25c762020-04-07 11:18:49 +0200230 *
231 * The nonce is not passed as a separate parameter but extracted
232 * from the entropy source as suggested in 8.6.7.
Jens Wiklander817466c2018-05-22 13:49:31 +0200233 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200234int mbedtls_hmac_drbg_seed(mbedtls_hmac_drbg_context *ctx,
235 const mbedtls_md_info_t *md_info,
236 int (*f_entropy)(void *, unsigned char *, size_t),
237 void *p_entropy,
238 const unsigned char *custom,
239 size_t len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200240{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200241 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200242 size_t md_size;
Jens Wiklander817466c2018-05-22 13:49:31 +0200243
Jens Wiklander32b31802023-10-06 16:59:46 +0200244 if ((ret = mbedtls_md_setup(&ctx->md_ctx, md_info, 1)) != 0) {
245 return ret;
246 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200247
Jerome Forissier79013242021-07-28 10:24:04 +0200248 /* The mutex is initialized iff the md context is set up. */
249#if defined(MBEDTLS_THREADING_C)
Jens Wiklander32b31802023-10-06 16:59:46 +0200250 mbedtls_mutex_init(&ctx->mutex);
Jerome Forissier79013242021-07-28 10:24:04 +0200251#endif
252
Jens Wiklander32b31802023-10-06 16:59:46 +0200253 md_size = mbedtls_md_get_size(md_info);
Jens Wiklander817466c2018-05-22 13:49:31 +0200254
255 /*
256 * Set initial working state.
257 * Use the V memory location, which is currently all 0, to initialize the
258 * MD context with an all-zero key. Then set V to its initial value.
259 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200260 if ((ret = mbedtls_md_hmac_starts(&ctx->md_ctx, ctx->V, md_size)) != 0) {
261 return ret;
262 }
263 memset(ctx->V, 0x01, md_size);
Jens Wiklander817466c2018-05-22 13:49:31 +0200264
265 ctx->f_entropy = f_entropy;
266 ctx->p_entropy = p_entropy;
267
Jens Wiklander32b31802023-10-06 16:59:46 +0200268 if (ctx->entropy_len == 0) {
Jerome Forissier5b25c762020-04-07 11:18:49 +0200269 /*
270 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
271 * each hash function, then according to SP800-90A rev1 10.1 table 2,
272 * min_entropy_len (in bits) is security_strength.
273 *
274 * (This also matches the sizes used in the NIST test vectors.)
275 */
276 ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
277 md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
278 32; /* better (256+) -> 256 bits */
279 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200280
Jens Wiklander32b31802023-10-06 16:59:46 +0200281 if ((ret = hmac_drbg_reseed_core(ctx, custom, len,
282 1 /* add nonce */)) != 0) {
283 return ret;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200284 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200285
Jens Wiklander32b31802023-10-06 16:59:46 +0200286 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200287}
288
289/*
290 * Set prediction resistance
291 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200292void mbedtls_hmac_drbg_set_prediction_resistance(mbedtls_hmac_drbg_context *ctx,
293 int resistance)
Jens Wiklander817466c2018-05-22 13:49:31 +0200294{
295 ctx->prediction_resistance = resistance;
296}
297
298/*
Jerome Forissier5b25c762020-04-07 11:18:49 +0200299 * Set entropy length grabbed for seeding
Jens Wiklander817466c2018-05-22 13:49:31 +0200300 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200301void mbedtls_hmac_drbg_set_entropy_len(mbedtls_hmac_drbg_context *ctx, size_t len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200302{
303 ctx->entropy_len = len;
304}
305
306/*
307 * Set reseed interval
308 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200309void mbedtls_hmac_drbg_set_reseed_interval(mbedtls_hmac_drbg_context *ctx, int interval)
Jens Wiklander817466c2018-05-22 13:49:31 +0200310{
311 ctx->reseed_interval = interval;
312}
313
314/*
315 * HMAC_DRBG random function with optional additional data:
316 * 10.1.2.5 (arabic) + 9.3 (Roman)
317 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200318int mbedtls_hmac_drbg_random_with_add(void *p_rng,
319 unsigned char *output, size_t out_len,
320 const unsigned char *additional, size_t add_len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200321{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200322 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200323 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
Jens Wiklander32b31802023-10-06 16:59:46 +0200324 size_t md_len = mbedtls_md_get_size(ctx->md_ctx.md_info);
Jens Wiklander817466c2018-05-22 13:49:31 +0200325 size_t left = out_len;
326 unsigned char *out = output;
327
328 /* II. Check request length */
Jens Wiklander32b31802023-10-06 16:59:46 +0200329 if (out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST) {
330 return MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG;
331 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200332
333 /* III. Check input length */
Jens Wiklander32b31802023-10-06 16:59:46 +0200334 if (add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT) {
335 return MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
336 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200337
338 /* 1. (aka VII and IX) Check reseed counter and PR */
Jens Wiklander32b31802023-10-06 16:59:46 +0200339 if (ctx->f_entropy != NULL && /* For no-reseeding instances */
340 (ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
341 ctx->reseed_counter > ctx->reseed_interval)) {
342 if ((ret = mbedtls_hmac_drbg_reseed(ctx, additional, add_len)) != 0) {
343 return ret;
344 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200345
346 add_len = 0; /* VII.4 */
347 }
348
349 /* 2. Use additional data if any */
Jens Wiklander32b31802023-10-06 16:59:46 +0200350 if (additional != NULL && add_len != 0) {
351 if ((ret = mbedtls_hmac_drbg_update(ctx,
352 additional, add_len)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100353 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200354 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100355 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200356
357 /* 3, 4, 5. Generate bytes */
Jens Wiklander32b31802023-10-06 16:59:46 +0200358 while (left != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200359 size_t use_len = left > md_len ? md_len : left;
360
Jens Wiklander32b31802023-10-06 16:59:46 +0200361 if ((ret = mbedtls_md_hmac_reset(&ctx->md_ctx)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100362 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200363 }
364 if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,
365 ctx->V, md_len)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100366 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200367 }
368 if ((ret = mbedtls_md_hmac_finish(&ctx->md_ctx, ctx->V)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100369 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200370 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200371
Jens Wiklander32b31802023-10-06 16:59:46 +0200372 memcpy(out, ctx->V, use_len);
Jens Wiklander817466c2018-05-22 13:49:31 +0200373 out += use_len;
374 left -= use_len;
375 }
376
377 /* 6. Update */
Jens Wiklander32b31802023-10-06 16:59:46 +0200378 if ((ret = mbedtls_hmac_drbg_update(ctx,
379 additional, add_len)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100380 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200381 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200382
383 /* 7. Update reseed counter */
384 ctx->reseed_counter++;
385
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100386exit:
Jens Wiklander817466c2018-05-22 13:49:31 +0200387 /* 8. Done */
Jens Wiklander32b31802023-10-06 16:59:46 +0200388 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200389}
390
391/*
392 * HMAC_DRBG random function
393 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200394int mbedtls_hmac_drbg_random(void *p_rng, unsigned char *output, size_t out_len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200395{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200396 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200397 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
398
399#if defined(MBEDTLS_THREADING_C)
Jens Wiklander32b31802023-10-06 16:59:46 +0200400 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
401 return ret;
402 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200403#endif
404
Jens Wiklander32b31802023-10-06 16:59:46 +0200405 ret = mbedtls_hmac_drbg_random_with_add(ctx, output, out_len, NULL, 0);
Jens Wiklander817466c2018-05-22 13:49:31 +0200406
407#if defined(MBEDTLS_THREADING_C)
Jens Wiklander32b31802023-10-06 16:59:46 +0200408 if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
409 return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
410 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200411#endif
412
Jens Wiklander32b31802023-10-06 16:59:46 +0200413 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200414}
415
416/*
Jerome Forissier79013242021-07-28 10:24:04 +0200417 * This function resets HMAC_DRBG context to the state immediately
418 * after initial call of mbedtls_hmac_drbg_init().
Jens Wiklander817466c2018-05-22 13:49:31 +0200419 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200420void mbedtls_hmac_drbg_free(mbedtls_hmac_drbg_context *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +0200421{
Jens Wiklander32b31802023-10-06 16:59:46 +0200422 if (ctx == NULL) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200423 return;
Jens Wiklander32b31802023-10-06 16:59:46 +0200424 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200425
426#if defined(MBEDTLS_THREADING_C)
Jerome Forissier79013242021-07-28 10:24:04 +0200427 /* The mutex is initialized iff the md context is set up. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200428 if (ctx->md_ctx.md_info != NULL) {
429 mbedtls_mutex_free(&ctx->mutex);
430 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200431#endif
Jens Wiklander32b31802023-10-06 16:59:46 +0200432 mbedtls_md_free(&ctx->md_ctx);
433 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_hmac_drbg_context));
Jerome Forissier79013242021-07-28 10:24:04 +0200434 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200435}
436
437#if defined(MBEDTLS_FS_IO)
Jens Wiklander32b31802023-10-06 16:59:46 +0200438int mbedtls_hmac_drbg_write_seed_file(mbedtls_hmac_drbg_context *ctx, const char *path)
Jens Wiklander817466c2018-05-22 13:49:31 +0200439{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200440 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200441 FILE *f;
Jens Wiklander32b31802023-10-06 16:59:46 +0200442 unsigned char buf[MBEDTLS_HMAC_DRBG_MAX_INPUT];
Jens Wiklander817466c2018-05-22 13:49:31 +0200443
Jens Wiklander32b31802023-10-06 16:59:46 +0200444 if ((f = fopen(path, "wb")) == NULL) {
445 return MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
446 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200447
Jens Wiklander32b31802023-10-06 16:59:46 +0200448 /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
449 mbedtls_setbuf(f, NULL);
450
451 if ((ret = mbedtls_hmac_drbg_random(ctx, buf, sizeof(buf))) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200452 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200453 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200454
Jens Wiklander32b31802023-10-06 16:59:46 +0200455 if (fwrite(buf, 1, sizeof(buf), f) != sizeof(buf)) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200456 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
457 goto exit;
458 }
459
460 ret = 0;
461
462exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200463 fclose(f);
464 mbedtls_platform_zeroize(buf, sizeof(buf));
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100465
Jens Wiklander32b31802023-10-06 16:59:46 +0200466 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200467}
468
Jens Wiklander32b31802023-10-06 16:59:46 +0200469int mbedtls_hmac_drbg_update_seed_file(mbedtls_hmac_drbg_context *ctx, const char *path)
Jens Wiklander817466c2018-05-22 13:49:31 +0200470{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100471 int ret = 0;
472 FILE *f = NULL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200473 size_t n;
Jens Wiklander32b31802023-10-06 16:59:46 +0200474 unsigned char buf[MBEDTLS_HMAC_DRBG_MAX_INPUT];
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100475 unsigned char c;
Jens Wiklander817466c2018-05-22 13:49:31 +0200476
Jens Wiklander32b31802023-10-06 16:59:46 +0200477 if ((f = fopen(path, "rb")) == NULL) {
478 return MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
479 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200480
Jens Wiklander32b31802023-10-06 16:59:46 +0200481 /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
482 mbedtls_setbuf(f, NULL);
483
484 n = fread(buf, 1, sizeof(buf), f);
485 if (fread(&c, 1, 1, f) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100486 ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
487 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200488 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200489 if (n == 0 || ferror(f)) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100490 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
491 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200492 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200493 fclose(f);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100494 f = NULL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200495
Jens Wiklander32b31802023-10-06 16:59:46 +0200496 ret = mbedtls_hmac_drbg_update(ctx, buf, n);
Jens Wiklander817466c2018-05-22 13:49:31 +0200497
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100498exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200499 mbedtls_platform_zeroize(buf, sizeof(buf));
500 if (f != NULL) {
501 fclose(f);
502 }
503 if (ret != 0) {
504 return ret;
505 }
506 return mbedtls_hmac_drbg_write_seed_file(ctx, path);
Jens Wiklander817466c2018-05-22 13:49:31 +0200507}
508#endif /* MBEDTLS_FS_IO */
509
510
511#if defined(MBEDTLS_SELF_TEST)
512
513#if !defined(MBEDTLS_SHA1_C)
514/* Dummy checkup routine */
Jens Wiklander32b31802023-10-06 16:59:46 +0200515int mbedtls_hmac_drbg_self_test(int verbose)
Jens Wiklander817466c2018-05-22 13:49:31 +0200516{
517 (void) verbose;
Jens Wiklander32b31802023-10-06 16:59:46 +0200518 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200519}
520#else
521
522#define OUTPUT_LEN 80
523
524/* From a NIST PR=true test vector */
525static const unsigned char entropy_pr[] = {
526 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
527 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
528 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
529 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
Jens Wiklander32b31802023-10-06 16:59:46 +0200530 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4
531};
Jens Wiklander817466c2018-05-22 13:49:31 +0200532static const unsigned char result_pr[OUTPUT_LEN] = {
533 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
534 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
535 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
536 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
537 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
538 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
Jens Wiklander32b31802023-10-06 16:59:46 +0200539 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44
540};
Jens Wiklander817466c2018-05-22 13:49:31 +0200541
542/* From a NIST PR=false test vector */
543static const unsigned char entropy_nopr[] = {
544 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
545 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
546 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
Jens Wiklander32b31802023-10-06 16:59:46 +0200547 0xe9, 0x9d, 0xfe, 0xdf
548};
Jens Wiklander817466c2018-05-22 13:49:31 +0200549static const unsigned char result_nopr[OUTPUT_LEN] = {
550 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
551 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
552 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
553 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
554 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
555 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
Jens Wiklander32b31802023-10-06 16:59:46 +0200556 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7
557};
Jens Wiklander817466c2018-05-22 13:49:31 +0200558
559/* "Entropy" from buffer */
560static size_t test_offset;
Jens Wiklander32b31802023-10-06 16:59:46 +0200561static int hmac_drbg_self_test_entropy(void *data,
562 unsigned char *buf, size_t len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200563{
564 const unsigned char *p = data;
Jens Wiklander32b31802023-10-06 16:59:46 +0200565 memcpy(buf, p + test_offset, len);
Jens Wiklander817466c2018-05-22 13:49:31 +0200566 test_offset += len;
Jens Wiklander32b31802023-10-06 16:59:46 +0200567 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200568}
569
Jens Wiklander32b31802023-10-06 16:59:46 +0200570#define CHK(c) if ((c) != 0) \
571 { \
572 if (verbose != 0) \
573 mbedtls_printf("failed\n"); \
574 return 1; \
575 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200576
577/*
578 * Checkup routine for HMAC_DRBG with SHA-1
579 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200580int mbedtls_hmac_drbg_self_test(int verbose)
Jens Wiklander817466c2018-05-22 13:49:31 +0200581{
582 mbedtls_hmac_drbg_context ctx;
583 unsigned char buf[OUTPUT_LEN];
Jens Wiklander32b31802023-10-06 16:59:46 +0200584 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
Jens Wiklander817466c2018-05-22 13:49:31 +0200585
Jens Wiklander32b31802023-10-06 16:59:46 +0200586 mbedtls_hmac_drbg_init(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200587
588 /*
589 * PR = True
590 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200591 if (verbose != 0) {
592 mbedtls_printf(" HMAC_DRBG (PR = True) : ");
593 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200594
595 test_offset = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +0200596 CHK(mbedtls_hmac_drbg_seed(&ctx, md_info,
597 hmac_drbg_self_test_entropy, (void *) entropy_pr,
598 NULL, 0));
599 mbedtls_hmac_drbg_set_prediction_resistance(&ctx, MBEDTLS_HMAC_DRBG_PR_ON);
600 CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));
601 CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));
602 CHK(memcmp(buf, result_pr, OUTPUT_LEN));
603 mbedtls_hmac_drbg_free(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200604
Jens Wiklander32b31802023-10-06 16:59:46 +0200605 mbedtls_hmac_drbg_free(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200606
Jens Wiklander32b31802023-10-06 16:59:46 +0200607 if (verbose != 0) {
608 mbedtls_printf("passed\n");
609 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200610
611 /*
612 * PR = False
613 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200614 if (verbose != 0) {
615 mbedtls_printf(" HMAC_DRBG (PR = False) : ");
616 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200617
Jens Wiklander32b31802023-10-06 16:59:46 +0200618 mbedtls_hmac_drbg_init(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200619
620 test_offset = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +0200621 CHK(mbedtls_hmac_drbg_seed(&ctx, md_info,
622 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
623 NULL, 0));
624 CHK(mbedtls_hmac_drbg_reseed(&ctx, NULL, 0));
625 CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));
626 CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));
627 CHK(memcmp(buf, result_nopr, OUTPUT_LEN));
628 mbedtls_hmac_drbg_free(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200629
Jens Wiklander32b31802023-10-06 16:59:46 +0200630 mbedtls_hmac_drbg_free(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200631
Jens Wiklander32b31802023-10-06 16:59:46 +0200632 if (verbose != 0) {
633 mbedtls_printf("passed\n");
634 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200635
Jens Wiklander32b31802023-10-06 16:59:46 +0200636 if (verbose != 0) {
637 mbedtls_printf("\n");
638 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200639
Jens Wiklander32b31802023-10-06 16:59:46 +0200640 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200641}
642#endif /* MBEDTLS_SHA1_C */
643#endif /* MBEDTLS_SELF_TEST */
644
645#endif /* MBEDTLS_HMAC_DRBG_C */