blob: acc4208cc37b410741c33ad58f5fd74218715a6a [file] [log] [blame]
Jens Wiklander817466c2018-05-22 13:49:31 +02001/*
2 * CTR_DRBG implementation based on AES-256 (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/*
Jens Wiklander3d3b0592019-03-20 15:30:29 +010020 * The NIST SP 800-90 DRBGs are described in the following publication.
Jens Wiklander817466c2018-05-22 13:49:31 +020021 *
22 * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
23 */
24
Jerome Forissier79013242021-07-28 10:24:04 +020025#include "common.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020026
27#if defined(MBEDTLS_CTR_DRBG_C)
28
29#include "mbedtls/ctr_drbg.h"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010030#include "mbedtls/platform_util.h"
Jerome Forissier11fa71b2020-04-20 17:17:56 +020031#include "mbedtls/error.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020032
33#include <string.h>
34
35#if defined(MBEDTLS_FS_IO)
36#include <stdio.h>
37#endif
38
Jens Wiklander817466c2018-05-22 13:49:31 +020039#include "mbedtls/platform.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020040
Jens Wiklander817466c2018-05-22 13:49:31 +020041/*
42 * CTR_DRBG context initialization
43 */
Jens Wiklander32b31802023-10-06 16:59:46 +020044void mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +020045{
Jens Wiklander32b31802023-10-06 16:59:46 +020046 memset(ctx, 0, sizeof(mbedtls_ctr_drbg_context));
47 mbedtls_aes_init(&ctx->aes_ctx);
Jerome Forissier11fa71b2020-04-20 17:17:56 +020048 /* Indicate that the entropy nonce length is not set explicitly.
49 * See mbedtls_ctr_drbg_set_nonce_len(). */
50 ctx->reseed_counter = -1;
Jens Wiklander817466c2018-05-22 13:49:31 +020051
Jerome Forissier79013242021-07-28 10:24:04 +020052 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
Jens Wiklander817466c2018-05-22 13:49:31 +020053}
54
Jerome Forissier79013242021-07-28 10:24:04 +020055/*
56 * This function resets CTR_DRBG context to the state immediately
57 * after initial call of mbedtls_ctr_drbg_init().
58 */
Jens Wiklander32b31802023-10-06 16:59:46 +020059void mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +020060{
Jens Wiklander32b31802023-10-06 16:59:46 +020061 if (ctx == NULL) {
Jens Wiklander817466c2018-05-22 13:49:31 +020062 return;
Jens Wiklander32b31802023-10-06 16:59:46 +020063 }
Jens Wiklander817466c2018-05-22 13:49:31 +020064
65#if defined(MBEDTLS_THREADING_C)
Jerome Forissier79013242021-07-28 10:24:04 +020066 /* The mutex is initialized iff f_entropy is set. */
Jens Wiklander32b31802023-10-06 16:59:46 +020067 if (ctx->f_entropy != NULL) {
68 mbedtls_mutex_free(&ctx->mutex);
69 }
Jens Wiklander817466c2018-05-22 13:49:31 +020070#endif
Jens Wiklander32b31802023-10-06 16:59:46 +020071 mbedtls_aes_free(&ctx->aes_ctx);
72 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ctr_drbg_context));
Jerome Forissier79013242021-07-28 10:24:04 +020073 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
74 ctx->reseed_counter = -1;
Jens Wiklander817466c2018-05-22 13:49:31 +020075}
76
Jens Wiklander32b31802023-10-06 16:59:46 +020077void mbedtls_ctr_drbg_set_prediction_resistance(mbedtls_ctr_drbg_context *ctx,
78 int resistance)
Jens Wiklander817466c2018-05-22 13:49:31 +020079{
80 ctx->prediction_resistance = resistance;
81}
82
Jens Wiklander32b31802023-10-06 16:59:46 +020083void mbedtls_ctr_drbg_set_entropy_len(mbedtls_ctr_drbg_context *ctx,
84 size_t len)
Jens Wiklander817466c2018-05-22 13:49:31 +020085{
86 ctx->entropy_len = len;
87}
88
Jens Wiklander32b31802023-10-06 16:59:46 +020089int mbedtls_ctr_drbg_set_nonce_len(mbedtls_ctr_drbg_context *ctx,
90 size_t len)
Jerome Forissier11fa71b2020-04-20 17:17:56 +020091{
92 /* If mbedtls_ctr_drbg_seed() has already been called, it's
93 * too late. Return the error code that's closest to making sense. */
Jens Wiklander32b31802023-10-06 16:59:46 +020094 if (ctx->f_entropy != NULL) {
95 return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
96 }
Jerome Forissier11fa71b2020-04-20 17:17:56 +020097
Jens Wiklander32b31802023-10-06 16:59:46 +020098 if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
99 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
100 }
101
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200102 /* This shouldn't be an issue because
103 * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible
104 * configuration, but make sure anyway. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200105 if (len > INT_MAX) {
106 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
107 }
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200108
109 /* For backward compatibility with Mbed TLS <= 2.19, store the
110 * entropy nonce length in a field that already exists, but isn't
111 * used until after the initial seeding. */
112 /* Due to the capping of len above, the value fits in an int. */
113 ctx->reseed_counter = (int) len;
Jens Wiklander32b31802023-10-06 16:59:46 +0200114 return 0;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200115}
116
Jens Wiklander32b31802023-10-06 16:59:46 +0200117void mbedtls_ctr_drbg_set_reseed_interval(mbedtls_ctr_drbg_context *ctx,
118 int interval)
Jens Wiklander817466c2018-05-22 13:49:31 +0200119{
120 ctx->reseed_interval = interval;
121}
122
Jens Wiklander32b31802023-10-06 16:59:46 +0200123static int block_cipher_df(unsigned char *output,
124 const unsigned char *data, size_t data_len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200125{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200126 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
127 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
Jens Wiklander817466c2018-05-22 13:49:31 +0200128 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
129 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
130 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
131 unsigned char *p, *iv;
132 mbedtls_aes_context aes_ctx;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100133 int ret = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200134
135 int i, j;
136 size_t buf_len, use_len;
137
Jens Wiklander32b31802023-10-06 16:59:46 +0200138 if (data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
139 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
140 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200141
Jens Wiklander32b31802023-10-06 16:59:46 +0200142 memset(buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
143 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16);
144 mbedtls_aes_init(&aes_ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200145
146 /*
147 * Construct IV (16 bytes) and S in buffer
148 * IV = Counter (in 32-bits) padded to 16 with zeroes
149 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
150 * data || 0x80
151 * (Total is padded to a multiple of 16-bytes with zeroes)
152 */
153 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Jens Wiklander32b31802023-10-06 16:59:46 +0200154 MBEDTLS_PUT_UINT32_BE(data_len, p, 0);
Jerome Forissier039e02d2022-08-09 17:10:15 +0200155 p += 4 + 3;
Jens Wiklander817466c2018-05-22 13:49:31 +0200156 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Jens Wiklander32b31802023-10-06 16:59:46 +0200157 memcpy(p, data, data_len);
Jens Wiklander817466c2018-05-22 13:49:31 +0200158 p[data_len] = 0x80;
159
160 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
161
Jens Wiklander32b31802023-10-06 16:59:46 +0200162 for (i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200163 key[i] = i;
Jens Wiklander32b31802023-10-06 16:59:46 +0200164 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200165
Jens Wiklander32b31802023-10-06 16:59:46 +0200166 if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, key,
167 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100168 goto exit;
169 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200170
171 /*
172 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
173 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200174 for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200175 p = buf;
Jens Wiklander32b31802023-10-06 16:59:46 +0200176 memset(chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE);
Jens Wiklander817466c2018-05-22 13:49:31 +0200177 use_len = buf_len;
178
Jens Wiklander32b31802023-10-06 16:59:46 +0200179 while (use_len > 0) {
180 mbedtls_xor(chain, chain, p, MBEDTLS_CTR_DRBG_BLOCKSIZE);
Jens Wiklander817466c2018-05-22 13:49:31 +0200181 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Jens Wiklander32b31802023-10-06 16:59:46 +0200182 use_len -= (use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE) ?
Jens Wiklander817466c2018-05-22 13:49:31 +0200183 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
184
Jens Wiklander32b31802023-10-06 16:59:46 +0200185 if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,
186 chain, chain)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100187 goto exit;
188 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200189 }
190
Jens Wiklander32b31802023-10-06 16:59:46 +0200191 memcpy(tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE);
Jens Wiklander817466c2018-05-22 13:49:31 +0200192
193 /*
194 * Update IV
195 */
196 buf[3]++;
197 }
198
199 /*
200 * Do final encryption with reduced data
201 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200202 if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, tmp,
203 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100204 goto exit;
205 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200206 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
207 p = output;
208
Jens Wiklander32b31802023-10-06 16:59:46 +0200209 for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
210 if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,
211 iv, iv)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100212 goto exit;
213 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200214 memcpy(p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE);
Jens Wiklander817466c2018-05-22 13:49:31 +0200215 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
216 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100217exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200218 mbedtls_aes_free(&aes_ctx);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100219 /*
Jens Wiklander32b31802023-10-06 16:59:46 +0200220 * tidy up the stack
221 */
222 mbedtls_platform_zeroize(buf, sizeof(buf));
223 mbedtls_platform_zeroize(tmp, sizeof(tmp));
224 mbedtls_platform_zeroize(key, sizeof(key));
225 mbedtls_platform_zeroize(chain, sizeof(chain));
226 if (0 != ret) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100227 /*
Jens Wiklander32b31802023-10-06 16:59:46 +0200228 * wipe partial seed from memory
229 */
230 mbedtls_platform_zeroize(output, MBEDTLS_CTR_DRBG_SEEDLEN);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100231 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200232
Jens Wiklander32b31802023-10-06 16:59:46 +0200233 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200234}
235
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100236/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
237 * ctr_drbg_update_internal(ctx, provided_data)
238 * implements
239 * CTR_DRBG_Update(provided_data, Key, V)
240 * with inputs and outputs
241 * ctx->aes_ctx = Key
242 * ctx->counter = V
243 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200244static int ctr_drbg_update_internal(mbedtls_ctr_drbg_context *ctx,
245 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN])
Jens Wiklander817466c2018-05-22 13:49:31 +0200246{
247 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
248 unsigned char *p = tmp;
249 int i, j;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100250 int ret = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200251
Jens Wiklander32b31802023-10-06 16:59:46 +0200252 memset(tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN);
Jens Wiklander817466c2018-05-22 13:49:31 +0200253
Jens Wiklander32b31802023-10-06 16:59:46 +0200254 for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200255 /*
256 * Increase counter
257 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200258 for (i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i--) {
259 if (++ctx->counter[i - 1] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200260 break;
Jens Wiklander32b31802023-10-06 16:59:46 +0200261 }
262 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200263
264 /*
265 * Crypt counter block
266 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200267 if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
268 ctx->counter, p)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100269 goto exit;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200270 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200271
272 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
273 }
274
Jens Wiklander32b31802023-10-06 16:59:46 +0200275 for (i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200276 tmp[i] ^= data[i];
Jens Wiklander32b31802023-10-06 16:59:46 +0200277 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200278
279 /*
280 * Update key and counter
281 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200282 if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, tmp,
283 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100284 goto exit;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200285 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200286 memcpy(ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
287 MBEDTLS_CTR_DRBG_BLOCKSIZE);
Jens Wiklander817466c2018-05-22 13:49:31 +0200288
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100289exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200290 mbedtls_platform_zeroize(tmp, sizeof(tmp));
291 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200292}
293
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100294/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
295 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
296 * implements
297 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
298 * security_strength) -> initial_working_state
299 * with inputs
300 * ctx->counter = all-bits-0
301 * ctx->aes_ctx = context from all-bits-0 key
302 * additional[:add_len] = entropy_input || nonce || personalization_string
303 * and with outputs
304 * ctx = initial_working_state
305 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200306int mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context *ctx,
307 const unsigned char *additional,
308 size_t add_len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200309{
310 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200311 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200312
Jens Wiklander32b31802023-10-06 16:59:46 +0200313 if (add_len == 0) {
314 return 0;
315 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200316
Jens Wiklander32b31802023-10-06 16:59:46 +0200317 if ((ret = block_cipher_df(add_input, additional, add_len)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100318 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200319 }
320 if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100321 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200322 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100323
324exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200325 mbedtls_platform_zeroize(add_input, sizeof(add_input));
326 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200327}
328
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100329/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200330 * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100331 * implements
332 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
333 * -> new_working_state
334 * with inputs
335 * ctx contains working_state
336 * additional[:len] = additional_input
337 * and entropy_input comes from calling ctx->f_entropy
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200338 * for (ctx->entropy_len + nonce_len) bytes
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100339 * and with output
340 * ctx contains new_working_state
341 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200342static int mbedtls_ctr_drbg_reseed_internal(mbedtls_ctr_drbg_context *ctx,
343 const unsigned char *additional,
344 size_t len,
345 size_t nonce_len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200346{
347 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
348 size_t seedlen = 0;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200349 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200350
Jens Wiklander32b31802023-10-06 16:59:46 +0200351 if (ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
352 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
353 }
354 if (nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len) {
355 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
356 }
357 if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len) {
358 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
359 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200360
Jens Wiklander32b31802023-10-06 16:59:46 +0200361 memset(seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT);
Jens Wiklander817466c2018-05-22 13:49:31 +0200362
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200363 /* Gather entropy_len bytes of entropy to seed state. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200364 if (0 != ctx->f_entropy(ctx->p_entropy, seed, ctx->entropy_len)) {
365 return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200366 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200367 seedlen += ctx->entropy_len;
368
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200369 /* Gather entropy for a nonce if requested. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200370 if (nonce_len != 0) {
371 if (0 != ctx->f_entropy(ctx->p_entropy, seed + seedlen, nonce_len)) {
372 return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200373 }
374 seedlen += nonce_len;
375 }
376
377 /* Add additional data if provided. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200378 if (additional != NULL && len != 0) {
379 memcpy(seed + seedlen, additional, len);
Jens Wiklander817466c2018-05-22 13:49:31 +0200380 seedlen += len;
381 }
382
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200383 /* Reduce to 384 bits. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200384 if ((ret = block_cipher_df(seed, seed, seedlen)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100385 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200386 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200387
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200388 /* Update state. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200389 if ((ret = ctr_drbg_update_internal(ctx, seed)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100390 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200391 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200392 ctx->reseed_counter = 1;
393
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100394exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200395 mbedtls_platform_zeroize(seed, sizeof(seed));
396 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200397}
398
Jens Wiklander32b31802023-10-06 16:59:46 +0200399int mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context *ctx,
400 const unsigned char *additional, size_t len)
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200401{
Jens Wiklander32b31802023-10-06 16:59:46 +0200402 return mbedtls_ctr_drbg_reseed_internal(ctx, additional, len, 0);
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200403}
404
405/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
406 * is sufficient to achieve the maximum security strength given the key
407 * size and entropy length. If there is enough entropy in the initial
408 * call to the entropy function to serve as both the entropy input and
409 * the nonce, don't make a second call to get a nonce. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200410static size_t good_nonce_len(size_t entropy_len)
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200411{
Jens Wiklander32b31802023-10-06 16:59:46 +0200412 if (entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2) {
413 return 0;
414 } else {
415 return (entropy_len + 1) / 2;
416 }
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200417}
418
Jerome Forissier5b25c762020-04-07 11:18:49 +0200419/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
420 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
421 * implements
422 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
423 * security_strength) -> initial_working_state
424 * with inputs
425 * custom[:len] = nonce || personalization_string
426 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
427 * and with outputs
428 * ctx = initial_working_state
429 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200430int mbedtls_ctr_drbg_seed(mbedtls_ctr_drbg_context *ctx,
431 int (*f_entropy)(void *, unsigned char *, size_t),
432 void *p_entropy,
433 const unsigned char *custom,
434 size_t len)
Jerome Forissier5b25c762020-04-07 11:18:49 +0200435{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200436 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200437 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200438 size_t nonce_len;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200439
Jens Wiklander32b31802023-10-06 16:59:46 +0200440 memset(key, 0, MBEDTLS_CTR_DRBG_KEYSIZE);
Jerome Forissier5b25c762020-04-07 11:18:49 +0200441
Jerome Forissier79013242021-07-28 10:24:04 +0200442 /* The mutex is initialized iff f_entropy is set. */
443#if defined(MBEDTLS_THREADING_C)
Jens Wiklander32b31802023-10-06 16:59:46 +0200444 mbedtls_mutex_init(&ctx->mutex);
Jerome Forissier79013242021-07-28 10:24:04 +0200445#endif
446
Jerome Forissier5b25c762020-04-07 11:18:49 +0200447 ctx->f_entropy = f_entropy;
448 ctx->p_entropy = p_entropy;
449
Jens Wiklander32b31802023-10-06 16:59:46 +0200450 if (ctx->entropy_len == 0) {
Jerome Forissier5b25c762020-04-07 11:18:49 +0200451 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Jens Wiklander32b31802023-10-06 16:59:46 +0200452 }
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200453 /* ctx->reseed_counter contains the desired amount of entropy to
454 * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
455 * If it's -1, indicating that the entropy nonce length was not set
456 * explicitly, use a sufficiently large nonce for security. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200457 nonce_len = (ctx->reseed_counter >= 0 ?
458 (size_t) ctx->reseed_counter :
459 good_nonce_len(ctx->entropy_len));
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200460
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200461 /* Initialize with an empty key. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200462 if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, key,
463 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
464 return ret;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200465 }
466
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200467 /* Do the initial seeding. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200468 if ((ret = mbedtls_ctr_drbg_reseed_internal(ctx, custom, len,
469 nonce_len)) != 0) {
470 return ret;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200471 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200472 return 0;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200473}
474
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100475/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
476 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
477 * implements
478 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
479 * -> working_state_after_reseed
480 * if required, then
481 * CTR_DRBG_Generate(working_state_after_reseed,
482 * requested_number_of_bits, additional_input)
483 * -> status, returned_bits, new_working_state
484 * with inputs
485 * ctx contains working_state
486 * requested_number_of_bits = 8 * output_len
487 * additional[:add_len] = additional_input
488 * and entropy_input comes from calling ctx->f_entropy
489 * and with outputs
490 * status = SUCCESS (this function does the reseed internally)
491 * returned_bits = output[:output_len]
492 * ctx contains new_working_state
493 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200494int mbedtls_ctr_drbg_random_with_add(void *p_rng,
495 unsigned char *output, size_t output_len,
496 const unsigned char *additional, size_t add_len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200497{
498 int ret = 0;
499 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
500 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
501 unsigned char *p = output;
502 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
503 int i;
504 size_t use_len;
505
Jens Wiklander32b31802023-10-06 16:59:46 +0200506 if (output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST) {
507 return MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG;
508 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200509
Jens Wiklander32b31802023-10-06 16:59:46 +0200510 if (add_len > MBEDTLS_CTR_DRBG_MAX_INPUT) {
511 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
512 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200513
Jens Wiklander32b31802023-10-06 16:59:46 +0200514 memset(add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN);
Jens Wiklander817466c2018-05-22 13:49:31 +0200515
Jens Wiklander32b31802023-10-06 16:59:46 +0200516 if (ctx->reseed_counter > ctx->reseed_interval ||
517 ctx->prediction_resistance) {
518 if ((ret = mbedtls_ctr_drbg_reseed(ctx, additional, add_len)) != 0) {
519 return ret;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100520 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200521 add_len = 0;
522 }
523
Jens Wiklander32b31802023-10-06 16:59:46 +0200524 if (add_len > 0) {
525 if ((ret = block_cipher_df(add_input, additional, add_len)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100526 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200527 }
528 if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100529 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200530 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200531 }
532
Jens Wiklander32b31802023-10-06 16:59:46 +0200533 while (output_len > 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200534 /*
535 * Increase counter
536 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200537 for (i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i--) {
538 if (++ctx->counter[i - 1] != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200539 break;
Jens Wiklander32b31802023-10-06 16:59:46 +0200540 }
541 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200542
543 /*
544 * Crypt counter block
545 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200546 if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
547 ctx->counter, tmp)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100548 goto exit;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200549 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200550
Jens Wiklander32b31802023-10-06 16:59:46 +0200551 use_len = (output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE)
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200552 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
Jens Wiklander817466c2018-05-22 13:49:31 +0200553 /*
554 * Copy random block to destination
555 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200556 memcpy(p, tmp, use_len);
Jens Wiklander817466c2018-05-22 13:49:31 +0200557 p += use_len;
558 output_len -= use_len;
559 }
560
Jens Wiklander32b31802023-10-06 16:59:46 +0200561 if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100562 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200563 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200564
565 ctx->reseed_counter++;
566
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100567exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200568 mbedtls_platform_zeroize(add_input, sizeof(add_input));
569 mbedtls_platform_zeroize(tmp, sizeof(tmp));
570 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200571}
572
Jens Wiklander32b31802023-10-06 16:59:46 +0200573int mbedtls_ctr_drbg_random(void *p_rng, unsigned char *output,
574 size_t output_len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200575{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200576 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200577 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
578
579#if defined(MBEDTLS_THREADING_C)
Jens Wiklander32b31802023-10-06 16:59:46 +0200580 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
581 return ret;
582 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200583#endif
584
Jens Wiklander32b31802023-10-06 16:59:46 +0200585 ret = mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, NULL, 0);
Jens Wiklander817466c2018-05-22 13:49:31 +0200586
587#if defined(MBEDTLS_THREADING_C)
Jens Wiklander32b31802023-10-06 16:59:46 +0200588 if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
589 return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
590 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200591#endif
592
Jens Wiklander32b31802023-10-06 16:59:46 +0200593 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200594}
595
596#if defined(MBEDTLS_FS_IO)
Jens Wiklander32b31802023-10-06 16:59:46 +0200597int mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context *ctx,
598 const char *path)
Jens Wiklander817466c2018-05-22 13:49:31 +0200599{
600 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
601 FILE *f;
Jens Wiklander32b31802023-10-06 16:59:46 +0200602 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT];
Jens Wiklander817466c2018-05-22 13:49:31 +0200603
Jens Wiklander32b31802023-10-06 16:59:46 +0200604 if ((f = fopen(path, "wb")) == NULL) {
605 return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200606 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200607
608 /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
609 mbedtls_setbuf(f, NULL);
610
611 if ((ret = mbedtls_ctr_drbg_random(ctx, buf,
612 MBEDTLS_CTR_DRBG_MAX_INPUT)) != 0) {
613 goto exit;
614 }
615
616 if (fwrite(buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f) !=
617 MBEDTLS_CTR_DRBG_MAX_INPUT) {
618 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
619 } else {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100620 ret = 0;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200621 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200622
623exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200624 mbedtls_platform_zeroize(buf, sizeof(buf));
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100625
Jens Wiklander32b31802023-10-06 16:59:46 +0200626 fclose(f);
627 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200628}
629
Jens Wiklander32b31802023-10-06 16:59:46 +0200630int mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context *ctx,
631 const char *path)
Jens Wiklander817466c2018-05-22 13:49:31 +0200632{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100633 int ret = 0;
634 FILE *f = NULL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200635 size_t n;
Jens Wiklander32b31802023-10-06 16:59:46 +0200636 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT];
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100637 unsigned char c;
Jens Wiklander817466c2018-05-22 13:49:31 +0200638
Jens Wiklander32b31802023-10-06 16:59:46 +0200639 if ((f = fopen(path, "rb")) == NULL) {
640 return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
641 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200642
Jens Wiklander32b31802023-10-06 16:59:46 +0200643 /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
644 mbedtls_setbuf(f, NULL);
645
646 n = fread(buf, 1, sizeof(buf), f);
647 if (fread(&c, 1, 1, f) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100648 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
649 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200650 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200651 if (n == 0 || ferror(f)) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100652 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
653 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200654 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200655 fclose(f);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100656 f = NULL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200657
Jens Wiklander32b31802023-10-06 16:59:46 +0200658 ret = mbedtls_ctr_drbg_update(ctx, buf, n);
Jens Wiklander817466c2018-05-22 13:49:31 +0200659
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100660exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200661 mbedtls_platform_zeroize(buf, sizeof(buf));
662 if (f != NULL) {
663 fclose(f);
664 }
665 if (ret != 0) {
666 return ret;
667 }
668 return mbedtls_ctr_drbg_write_seed_file(ctx, path);
Jens Wiklander817466c2018-05-22 13:49:31 +0200669}
670#endif /* MBEDTLS_FS_IO */
671
672#if defined(MBEDTLS_SELF_TEST)
673
Jerome Forissier79013242021-07-28 10:24:04 +0200674/* The CTR_DRBG NIST test vectors used here are available at
675 * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip
676 *
677 * The parameters used to derive the test data are:
678 *
679 * [AES-128 use df]
680 * [PredictionResistance = True/False]
681 * [EntropyInputLen = 128]
682 * [NonceLen = 64]
683 * [PersonalizationStringLen = 128]
684 * [AdditionalInputLen = 0]
685 * [ReturnedBitsLen = 512]
686 *
687 * [AES-256 use df]
688 * [PredictionResistance = True/False]
689 * [EntropyInputLen = 256]
690 * [NonceLen = 128]
691 * [PersonalizationStringLen = 256]
692 * [AdditionalInputLen = 0]
693 * [ReturnedBitsLen = 512]
694 *
695 */
Jens Wiklander817466c2018-05-22 13:49:31 +0200696
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200697#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
Jerome Forissier79013242021-07-28 10:24:04 +0200698static const unsigned char entropy_source_pr[] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200699{ 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb,
700 0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92,
701 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8,
702 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20,
703 0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0,
704 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad,
705 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 };
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200706
Jerome Forissier79013242021-07-28 10:24:04 +0200707static const unsigned char entropy_source_nopr[] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200708{ 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45,
709 0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9,
710 0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20,
711 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f,
712 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c };
Jerome Forissier79013242021-07-28 10:24:04 +0200713
714static const unsigned char pers_pr[] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200715{ 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a,
716 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad };
Jerome Forissier79013242021-07-28 10:24:04 +0200717
718static const unsigned char pers_nopr[] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200719{ 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c,
720 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f };
Jerome Forissier79013242021-07-28 10:24:04 +0200721
722static const unsigned char result_pr[] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200723{ 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66,
724 0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff,
725 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10,
726 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30,
727 0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4,
728 0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc,
729 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06,
730 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf };
Jerome Forissier79013242021-07-28 10:24:04 +0200731
732static const unsigned char result_nopr[] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200733{ 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13,
734 0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0,
735 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf,
736 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2,
737 0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7,
738 0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2,
739 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02,
740 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 };
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200741#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Jens Wiklander817466c2018-05-22 13:49:31 +0200742
Jerome Forissier79013242021-07-28 10:24:04 +0200743static const unsigned char entropy_source_pr[] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200744{ 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49,
745 0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a,
746 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85,
747 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e,
748 0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15,
749 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45,
750 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8,
751 0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c,
752 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3,
753 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce,
754 0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e,
755 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76,
756 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77,
757 0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe };
Jerome Forissier79013242021-07-28 10:24:04 +0200758
759static const unsigned char entropy_source_nopr[] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200760{ 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d,
761 0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0,
762 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73,
763 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c,
764 0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2,
765 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1,
766 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a,
767 0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb,
768 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a,
769 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 };
Jerome Forissier79013242021-07-28 10:24:04 +0200770
771static const unsigned char pers_pr[] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200772{ 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33,
773 0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e,
774 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0,
775 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 };
Jerome Forissier79013242021-07-28 10:24:04 +0200776
777static const unsigned char pers_nopr[] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200778{ 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29,
779 0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf,
780 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb,
781 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b };
Jerome Forissier79013242021-07-28 10:24:04 +0200782
783static const unsigned char result_pr[] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200784{ 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85,
785 0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d,
786 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62,
787 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d,
788 0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb,
789 0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39,
790 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40,
791 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 };
Jerome Forissier79013242021-07-28 10:24:04 +0200792
793static const unsigned char result_nopr[] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200794{ 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad,
795 0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3,
796 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b,
797 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14,
798 0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54,
799 0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30,
800 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a,
801 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 };
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200802#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Jens Wiklander817466c2018-05-22 13:49:31 +0200803
804static size_t test_offset;
Jens Wiklander32b31802023-10-06 16:59:46 +0200805static int ctr_drbg_self_test_entropy(void *data, unsigned char *buf,
806 size_t len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200807{
808 const unsigned char *p = data;
Jens Wiklander32b31802023-10-06 16:59:46 +0200809 memcpy(buf, p + test_offset, len);
Jens Wiklander817466c2018-05-22 13:49:31 +0200810 test_offset += len;
Jens Wiklander32b31802023-10-06 16:59:46 +0200811 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200812}
813
Jens Wiklander32b31802023-10-06 16:59:46 +0200814#define CHK(c) if ((c) != 0) \
815 { \
816 if (verbose != 0) \
817 mbedtls_printf("failed\n"); \
818 return 1; \
819 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200820
Jerome Forissier039e02d2022-08-09 17:10:15 +0200821#define SELF_TEST_OUTPUT_DISCARD_LENGTH 64
Jerome Forissier79013242021-07-28 10:24:04 +0200822
Jens Wiklander817466c2018-05-22 13:49:31 +0200823/*
824 * Checkup routine
825 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200826int mbedtls_ctr_drbg_self_test(int verbose)
Jens Wiklander817466c2018-05-22 13:49:31 +0200827{
828 mbedtls_ctr_drbg_context ctx;
Jens Wiklander32b31802023-10-06 16:59:46 +0200829 unsigned char buf[sizeof(result_pr)];
Jens Wiklander817466c2018-05-22 13:49:31 +0200830
Jens Wiklander32b31802023-10-06 16:59:46 +0200831 mbedtls_ctr_drbg_init(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200832
833 /*
834 * Based on a NIST CTR_DRBG test vector (PR = True)
835 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200836 if (verbose != 0) {
837 mbedtls_printf(" CTR_DRBG (PR = TRUE) : ");
838 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200839
840 test_offset = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +0200841 mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
842 mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2);
843 CHK(mbedtls_ctr_drbg_seed(&ctx,
844 ctr_drbg_self_test_entropy,
845 (void *) entropy_source_pr,
846 pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE));
847 mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_ON);
848 CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH));
849 CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_pr)));
850 CHK(memcmp(buf, result_pr, sizeof(result_pr)));
Jens Wiklander817466c2018-05-22 13:49:31 +0200851
Jens Wiklander32b31802023-10-06 16:59:46 +0200852 mbedtls_ctr_drbg_free(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200853
Jens Wiklander32b31802023-10-06 16:59:46 +0200854 if (verbose != 0) {
855 mbedtls_printf("passed\n");
856 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200857
858 /*
859 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
860 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200861 if (verbose != 0) {
862 mbedtls_printf(" CTR_DRBG (PR = FALSE): ");
863 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200864
Jens Wiklander32b31802023-10-06 16:59:46 +0200865 mbedtls_ctr_drbg_init(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200866
867 test_offset = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +0200868 mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
869 mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2);
870 CHK(mbedtls_ctr_drbg_seed(&ctx,
871 ctr_drbg_self_test_entropy,
872 (void *) entropy_source_nopr,
873 pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE));
874 CHK(mbedtls_ctr_drbg_reseed(&ctx, NULL, 0));
875 CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH));
876 CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_nopr)));
877 CHK(memcmp(buf, result_nopr, sizeof(result_nopr)));
Jens Wiklander817466c2018-05-22 13:49:31 +0200878
Jens Wiklander32b31802023-10-06 16:59:46 +0200879 mbedtls_ctr_drbg_free(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200880
Jens Wiklander32b31802023-10-06 16:59:46 +0200881 if (verbose != 0) {
882 mbedtls_printf("passed\n");
883 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200884
Jens Wiklander32b31802023-10-06 16:59:46 +0200885 if (verbose != 0) {
886 mbedtls_printf("\n");
887 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200888
Jens Wiklander32b31802023-10-06 16:59:46 +0200889 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200890}
891#endif /* MBEDTLS_SELF_TEST */
892
893#endif /* MBEDTLS_CTR_DRBG_C */