blob: b82044eb7d26b986f86f6eb9b9f43d619e149a21 [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
Tom Van Eyckb0563632024-06-13 16:20:14 +02005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Jens Wiklander817466c2018-05-22 13:49:31 +02006 */
7/*
Jens Wiklander3d3b0592019-03-20 15:30:29 +01008 * The NIST SP 800-90 DRBGs are described in the following publication.
Jens Wiklander817466c2018-05-22 13:49:31 +02009 *
Tom Van Eyckb0563632024-06-13 16:20:14 +020010 * https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-90r.pdf
Jens Wiklander817466c2018-05-22 13:49:31 +020011 */
12
Jerome Forissier79013242021-07-28 10:24:04 +020013#include "common.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020014
15#if defined(MBEDTLS_CTR_DRBG_C)
16
Tom Van Eyckb0563632024-06-13 16:20:14 +020017#include "ctr.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020018#include "mbedtls/ctr_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
Tom Van Eyckb0563632024-06-13 16:20:14 +020028/* Using error translation functions from PSA to MbedTLS */
Sungbae Yoo4d211f32024-11-19 02:47:55 +000029#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
Tom Van Eyckb0563632024-06-13 16:20:14 +020030#include "psa_util_internal.h"
31#endif
32
Jens Wiklander817466c2018-05-22 13:49:31 +020033#include "mbedtls/platform.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020034
Sungbae Yoo4d211f32024-11-19 02:47:55 +000035#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
Tom Van Eyckb0563632024-06-13 16:20:14 +020036static psa_status_t ctr_drbg_setup_psa_context(mbedtls_ctr_drbg_psa_context *psa_ctx,
37 unsigned char *key, size_t key_len)
38{
39 psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
40 psa_status_t status;
41
42 psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT);
43 psa_set_key_algorithm(&key_attr, PSA_ALG_ECB_NO_PADDING);
44 psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
45 status = psa_import_key(&key_attr, key, key_len, &psa_ctx->key_id);
46 if (status != PSA_SUCCESS) {
47 goto exit;
48 }
49
50 status = psa_cipher_encrypt_setup(&psa_ctx->operation, psa_ctx->key_id, PSA_ALG_ECB_NO_PADDING);
51 if (status != PSA_SUCCESS) {
52 goto exit;
53 }
54
55exit:
56 psa_reset_key_attributes(&key_attr);
57 return status;
58}
59
60static void ctr_drbg_destroy_psa_contex(mbedtls_ctr_drbg_psa_context *psa_ctx)
61{
62 psa_cipher_abort(&psa_ctx->operation);
63 psa_destroy_key(psa_ctx->key_id);
64
65 psa_ctx->operation = psa_cipher_operation_init();
66 psa_ctx->key_id = MBEDTLS_SVC_KEY_ID_INIT;
67}
68#endif
69
Jens Wiklander817466c2018-05-22 13:49:31 +020070/*
71 * CTR_DRBG context initialization
72 */
Jens Wiklander32b31802023-10-06 16:59:46 +020073void mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +020074{
Jens Wiklander32b31802023-10-06 16:59:46 +020075 memset(ctx, 0, sizeof(mbedtls_ctr_drbg_context));
Sungbae Yoo4d211f32024-11-19 02:47:55 +000076#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
Tom Van Eyckb0563632024-06-13 16:20:14 +020077 ctx->psa_ctx.key_id = MBEDTLS_SVC_KEY_ID_INIT;
78 ctx->psa_ctx.operation = psa_cipher_operation_init();
Sungbae Yoo4d211f32024-11-19 02:47:55 +000079#else
80 mbedtls_aes_init(&ctx->aes_ctx);
Tom Van Eyckb0563632024-06-13 16:20:14 +020081#endif
Jerome Forissier11fa71b2020-04-20 17:17:56 +020082 /* Indicate that the entropy nonce length is not set explicitly.
83 * See mbedtls_ctr_drbg_set_nonce_len(). */
84 ctx->reseed_counter = -1;
Jens Wiklander817466c2018-05-22 13:49:31 +020085
Jerome Forissier79013242021-07-28 10:24:04 +020086 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
Jens Wiklander817466c2018-05-22 13:49:31 +020087}
88
Jerome Forissier79013242021-07-28 10:24:04 +020089/*
90 * This function resets CTR_DRBG context to the state immediately
91 * after initial call of mbedtls_ctr_drbg_init().
92 */
Jens Wiklander32b31802023-10-06 16:59:46 +020093void mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +020094{
Jens Wiklander32b31802023-10-06 16:59:46 +020095 if (ctx == NULL) {
Jens Wiklander817466c2018-05-22 13:49:31 +020096 return;
Jens Wiklander32b31802023-10-06 16:59:46 +020097 }
Jens Wiklander817466c2018-05-22 13:49:31 +020098
99#if defined(MBEDTLS_THREADING_C)
Jerome Forissier79013242021-07-28 10:24:04 +0200100 /* The mutex is initialized iff f_entropy is set. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200101 if (ctx->f_entropy != NULL) {
102 mbedtls_mutex_free(&ctx->mutex);
103 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200104#endif
Sungbae Yoo4d211f32024-11-19 02:47:55 +0000105#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
Tom Van Eyckb0563632024-06-13 16:20:14 +0200106 ctr_drbg_destroy_psa_contex(&ctx->psa_ctx);
Sungbae Yoo4d211f32024-11-19 02:47:55 +0000107#else
108 mbedtls_aes_free(&ctx->aes_ctx);
Tom Van Eyckb0563632024-06-13 16:20:14 +0200109#endif
Jens Wiklander32b31802023-10-06 16:59:46 +0200110 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ctr_drbg_context));
Jerome Forissier79013242021-07-28 10:24:04 +0200111 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
112 ctx->reseed_counter = -1;
Jens Wiklander817466c2018-05-22 13:49:31 +0200113}
114
Jens Wiklander32b31802023-10-06 16:59:46 +0200115void mbedtls_ctr_drbg_set_prediction_resistance(mbedtls_ctr_drbg_context *ctx,
116 int resistance)
Jens Wiklander817466c2018-05-22 13:49:31 +0200117{
118 ctx->prediction_resistance = resistance;
119}
120
Jens Wiklander32b31802023-10-06 16:59:46 +0200121void mbedtls_ctr_drbg_set_entropy_len(mbedtls_ctr_drbg_context *ctx,
122 size_t len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200123{
124 ctx->entropy_len = len;
125}
126
Jens Wiklander32b31802023-10-06 16:59:46 +0200127int mbedtls_ctr_drbg_set_nonce_len(mbedtls_ctr_drbg_context *ctx,
128 size_t len)
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200129{
130 /* If mbedtls_ctr_drbg_seed() has already been called, it's
131 * too late. Return the error code that's closest to making sense. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200132 if (ctx->f_entropy != NULL) {
133 return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
134 }
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200135
Jens Wiklander32b31802023-10-06 16:59:46 +0200136 if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
137 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
138 }
139
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200140 /* This shouldn't be an issue because
141 * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible
142 * configuration, but make sure anyway. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200143 if (len > INT_MAX) {
144 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
145 }
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200146
147 /* For backward compatibility with Mbed TLS <= 2.19, store the
148 * entropy nonce length in a field that already exists, but isn't
149 * used until after the initial seeding. */
150 /* Due to the capping of len above, the value fits in an int. */
151 ctx->reseed_counter = (int) len;
Jens Wiklander32b31802023-10-06 16:59:46 +0200152 return 0;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200153}
154
Jens Wiklander32b31802023-10-06 16:59:46 +0200155void mbedtls_ctr_drbg_set_reseed_interval(mbedtls_ctr_drbg_context *ctx,
156 int interval)
Jens Wiklander817466c2018-05-22 13:49:31 +0200157{
158 ctx->reseed_interval = interval;
159}
160
Jens Wiklander32b31802023-10-06 16:59:46 +0200161static int block_cipher_df(unsigned char *output,
162 const unsigned char *data, size_t data_len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200163{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200164 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
165 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
Jens Wiklander817466c2018-05-22 13:49:31 +0200166 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
167 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
168 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
169 unsigned char *p, *iv;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100170 int ret = 0;
Sungbae Yoo4d211f32024-11-19 02:47:55 +0000171#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
Tom Van Eyckb0563632024-06-13 16:20:14 +0200172 psa_status_t status;
173 size_t tmp_len;
174 mbedtls_ctr_drbg_psa_context psa_ctx;
175
176 psa_ctx.key_id = MBEDTLS_SVC_KEY_ID_INIT;
177 psa_ctx.operation = psa_cipher_operation_init();
Sungbae Yoo4d211f32024-11-19 02:47:55 +0000178#else
179 mbedtls_aes_context aes_ctx;
Tom Van Eyckb0563632024-06-13 16:20:14 +0200180#endif
Jens Wiklander817466c2018-05-22 13:49:31 +0200181
182 int i, j;
183 size_t buf_len, use_len;
184
Jens Wiklander32b31802023-10-06 16:59:46 +0200185 if (data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
186 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
187 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200188
Jens Wiklander32b31802023-10-06 16:59:46 +0200189 memset(buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
190 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16);
Jens Wiklander817466c2018-05-22 13:49:31 +0200191
192 /*
193 * Construct IV (16 bytes) and S in buffer
194 * IV = Counter (in 32-bits) padded to 16 with zeroes
195 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
196 * data || 0x80
197 * (Total is padded to a multiple of 16-bytes with zeroes)
198 */
199 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Jens Wiklander32b31802023-10-06 16:59:46 +0200200 MBEDTLS_PUT_UINT32_BE(data_len, p, 0);
Jerome Forissier039e02d2022-08-09 17:10:15 +0200201 p += 4 + 3;
Jens Wiklander817466c2018-05-22 13:49:31 +0200202 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Jens Wiklander32b31802023-10-06 16:59:46 +0200203 memcpy(p, data, data_len);
Jens Wiklander817466c2018-05-22 13:49:31 +0200204 p[data_len] = 0x80;
205
206 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
207
Jens Wiklander32b31802023-10-06 16:59:46 +0200208 for (i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200209 key[i] = i;
Jens Wiklander32b31802023-10-06 16:59:46 +0200210 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200211
Sungbae Yoo4d211f32024-11-19 02:47:55 +0000212#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
213 status = ctr_drbg_setup_psa_context(&psa_ctx, key, sizeof(key));
214 if (status != PSA_SUCCESS) {
215 ret = psa_generic_status_to_mbedtls(status);
216 goto exit;
217 }
218#else
Tom Van Eyckb0563632024-06-13 16:20:14 +0200219 mbedtls_aes_init(&aes_ctx);
220
Jens Wiklander32b31802023-10-06 16:59:46 +0200221 if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, key,
222 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100223 goto exit;
224 }
Tom Van Eyckb0563632024-06-13 16:20:14 +0200225#endif
Jens Wiklander817466c2018-05-22 13:49:31 +0200226
227 /*
228 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
229 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200230 for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200231 p = buf;
Jens Wiklander32b31802023-10-06 16:59:46 +0200232 memset(chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE);
Jens Wiklander817466c2018-05-22 13:49:31 +0200233 use_len = buf_len;
234
Jens Wiklander32b31802023-10-06 16:59:46 +0200235 while (use_len > 0) {
236 mbedtls_xor(chain, chain, p, MBEDTLS_CTR_DRBG_BLOCKSIZE);
Jens Wiklander817466c2018-05-22 13:49:31 +0200237 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Jens Wiklander32b31802023-10-06 16:59:46 +0200238 use_len -= (use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE) ?
Jens Wiklander817466c2018-05-22 13:49:31 +0200239 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
240
Sungbae Yoo4d211f32024-11-19 02:47:55 +0000241#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
Tom Van Eyckb0563632024-06-13 16:20:14 +0200242 status = psa_cipher_update(&psa_ctx.operation, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE,
243 chain, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);
244 if (status != PSA_SUCCESS) {
245 ret = psa_generic_status_to_mbedtls(status);
246 goto exit;
247 }
Sungbae Yoo4d211f32024-11-19 02:47:55 +0000248#else
249 if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,
250 chain, chain)) != 0) {
251 goto exit;
252 }
Tom Van Eyckb0563632024-06-13 16:20:14 +0200253#endif
Jens Wiklander817466c2018-05-22 13:49:31 +0200254 }
255
Jens Wiklander32b31802023-10-06 16:59:46 +0200256 memcpy(tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE);
Jens Wiklander817466c2018-05-22 13:49:31 +0200257
258 /*
259 * Update IV
260 */
261 buf[3]++;
262 }
263
264 /*
265 * Do final encryption with reduced data
266 */
Sungbae Yoo4d211f32024-11-19 02:47:55 +0000267#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
Tom Van Eyckb0563632024-06-13 16:20:14 +0200268 ctr_drbg_destroy_psa_contex(&psa_ctx);
269
270 status = ctr_drbg_setup_psa_context(&psa_ctx, tmp, MBEDTLS_CTR_DRBG_KEYSIZE);
271 if (status != PSA_SUCCESS) {
272 ret = psa_generic_status_to_mbedtls(status);
273 goto exit;
274 }
Sungbae Yoo4d211f32024-11-19 02:47:55 +0000275#else
276 if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, tmp,
277 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
278 goto exit;
279 }
Tom Van Eyckb0563632024-06-13 16:20:14 +0200280#endif
Jens Wiklander817466c2018-05-22 13:49:31 +0200281 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
282 p = output;
283
Jens Wiklander32b31802023-10-06 16:59:46 +0200284 for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
Sungbae Yoo4d211f32024-11-19 02:47:55 +0000285#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
Tom Van Eyckb0563632024-06-13 16:20:14 +0200286 status = psa_cipher_update(&psa_ctx.operation, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE,
287 iv, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);
288 if (status != PSA_SUCCESS) {
289 ret = psa_generic_status_to_mbedtls(status);
290 goto exit;
291 }
Sungbae Yoo4d211f32024-11-19 02:47:55 +0000292#else
293 if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,
294 iv, iv)) != 0) {
295 goto exit;
296 }
Tom Van Eyckb0563632024-06-13 16:20:14 +0200297#endif
Jens Wiklander32b31802023-10-06 16:59:46 +0200298 memcpy(p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE);
Jens Wiklander817466c2018-05-22 13:49:31 +0200299 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
300 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100301exit:
Sungbae Yoo4d211f32024-11-19 02:47:55 +0000302#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
Tom Van Eyckb0563632024-06-13 16:20:14 +0200303 ctr_drbg_destroy_psa_contex(&psa_ctx);
Sungbae Yoo4d211f32024-11-19 02:47:55 +0000304#else
305 mbedtls_aes_free(&aes_ctx);
Tom Van Eyckb0563632024-06-13 16:20:14 +0200306#endif
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100307 /*
Jens Wiklander32b31802023-10-06 16:59:46 +0200308 * tidy up the stack
309 */
310 mbedtls_platform_zeroize(buf, sizeof(buf));
311 mbedtls_platform_zeroize(tmp, sizeof(tmp));
312 mbedtls_platform_zeroize(key, sizeof(key));
313 mbedtls_platform_zeroize(chain, sizeof(chain));
314 if (0 != ret) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100315 /*
Jens Wiklander32b31802023-10-06 16:59:46 +0200316 * wipe partial seed from memory
317 */
318 mbedtls_platform_zeroize(output, MBEDTLS_CTR_DRBG_SEEDLEN);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100319 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200320
Jens Wiklander32b31802023-10-06 16:59:46 +0200321 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200322}
323
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100324/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
325 * ctr_drbg_update_internal(ctx, provided_data)
326 * implements
327 * CTR_DRBG_Update(provided_data, Key, V)
328 * with inputs and outputs
329 * ctx->aes_ctx = Key
330 * ctx->counter = V
331 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200332static int ctr_drbg_update_internal(mbedtls_ctr_drbg_context *ctx,
333 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN])
Jens Wiklander817466c2018-05-22 13:49:31 +0200334{
335 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
336 unsigned char *p = tmp;
Tom Van Eyckb0563632024-06-13 16:20:14 +0200337 int j;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100338 int ret = 0;
Sungbae Yoo4d211f32024-11-19 02:47:55 +0000339#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
Tom Van Eyckb0563632024-06-13 16:20:14 +0200340 psa_status_t status;
341 size_t tmp_len;
342#endif
Jens Wiklander817466c2018-05-22 13:49:31 +0200343
Jens Wiklander32b31802023-10-06 16:59:46 +0200344 memset(tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN);
Jens Wiklander817466c2018-05-22 13:49:31 +0200345
Jens Wiklander32b31802023-10-06 16:59:46 +0200346 for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200347 /*
348 * Increase counter
349 */
Tom Van Eyckb0563632024-06-13 16:20:14 +0200350 mbedtls_ctr_increment_counter(ctx->counter);
Jens Wiklander817466c2018-05-22 13:49:31 +0200351
352 /*
353 * Crypt counter block
354 */
Sungbae Yoo4d211f32024-11-19 02:47:55 +0000355#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
Tom Van Eyckb0563632024-06-13 16:20:14 +0200356 status = psa_cipher_update(&ctx->psa_ctx.operation, ctx->counter, sizeof(ctx->counter),
357 p, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);
358 if (status != PSA_SUCCESS) {
359 ret = psa_generic_status_to_mbedtls(status);
360 goto exit;
361 }
Sungbae Yoo4d211f32024-11-19 02:47:55 +0000362#else
363 if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
364 ctx->counter, p)) != 0) {
365 goto exit;
366 }
Tom Van Eyckb0563632024-06-13 16:20:14 +0200367#endif
Jens Wiklander817466c2018-05-22 13:49:31 +0200368
369 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
370 }
371
Tom Van Eyckb0563632024-06-13 16:20:14 +0200372 mbedtls_xor(tmp, tmp, data, MBEDTLS_CTR_DRBG_SEEDLEN);
Jens Wiklander817466c2018-05-22 13:49:31 +0200373
374 /*
375 * Update key and counter
376 */
Sungbae Yoo4d211f32024-11-19 02:47:55 +0000377#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
Tom Van Eyckb0563632024-06-13 16:20:14 +0200378 ctr_drbg_destroy_psa_contex(&ctx->psa_ctx);
379
380 status = ctr_drbg_setup_psa_context(&ctx->psa_ctx, tmp, MBEDTLS_CTR_DRBG_KEYSIZE);
381 if (status != PSA_SUCCESS) {
382 ret = psa_generic_status_to_mbedtls(status);
383 goto exit;
384 }
Sungbae Yoo4d211f32024-11-19 02:47:55 +0000385#else
386 if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, tmp,
387 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
388 goto exit;
389 }
Tom Van Eyckb0563632024-06-13 16:20:14 +0200390#endif
Jens Wiklander32b31802023-10-06 16:59:46 +0200391 memcpy(ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
392 MBEDTLS_CTR_DRBG_BLOCKSIZE);
Jens Wiklander817466c2018-05-22 13:49:31 +0200393
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100394exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200395 mbedtls_platform_zeroize(tmp, sizeof(tmp));
396 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200397}
398
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100399/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
400 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
401 * implements
402 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
403 * security_strength) -> initial_working_state
404 * with inputs
405 * ctx->counter = all-bits-0
406 * ctx->aes_ctx = context from all-bits-0 key
407 * additional[:add_len] = entropy_input || nonce || personalization_string
408 * and with outputs
409 * ctx = initial_working_state
410 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200411int mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context *ctx,
412 const unsigned char *additional,
413 size_t add_len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200414{
415 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200416 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200417
Jens Wiklander32b31802023-10-06 16:59:46 +0200418 if (add_len == 0) {
419 return 0;
420 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200421
Jens Wiklander32b31802023-10-06 16:59:46 +0200422 if ((ret = block_cipher_df(add_input, additional, add_len)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100423 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200424 }
425 if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100426 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200427 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100428
429exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200430 mbedtls_platform_zeroize(add_input, sizeof(add_input));
431 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200432}
433
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100434/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200435 * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100436 * implements
437 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
438 * -> new_working_state
439 * with inputs
440 * ctx contains working_state
441 * additional[:len] = additional_input
442 * and entropy_input comes from calling ctx->f_entropy
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200443 * for (ctx->entropy_len + nonce_len) bytes
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100444 * and with output
445 * ctx contains new_working_state
446 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200447static int mbedtls_ctr_drbg_reseed_internal(mbedtls_ctr_drbg_context *ctx,
448 const unsigned char *additional,
449 size_t len,
450 size_t nonce_len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200451{
452 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
453 size_t seedlen = 0;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200454 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200455
Jens Wiklander32b31802023-10-06 16:59:46 +0200456 if (ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
457 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
458 }
459 if (nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len) {
460 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
461 }
462 if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len) {
463 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
464 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200465
Jens Wiklander32b31802023-10-06 16:59:46 +0200466 memset(seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT);
Jens Wiklander817466c2018-05-22 13:49:31 +0200467
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200468 /* Gather entropy_len bytes of entropy to seed state. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200469 if (0 != ctx->f_entropy(ctx->p_entropy, seed, ctx->entropy_len)) {
470 return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200471 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200472 seedlen += ctx->entropy_len;
473
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200474 /* Gather entropy for a nonce if requested. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200475 if (nonce_len != 0) {
476 if (0 != ctx->f_entropy(ctx->p_entropy, seed + seedlen, nonce_len)) {
477 return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200478 }
479 seedlen += nonce_len;
480 }
481
482 /* Add additional data if provided. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200483 if (additional != NULL && len != 0) {
484 memcpy(seed + seedlen, additional, len);
Jens Wiklander817466c2018-05-22 13:49:31 +0200485 seedlen += len;
486 }
487
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200488 /* Reduce to 384 bits. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200489 if ((ret = block_cipher_df(seed, seed, seedlen)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100490 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200491 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200492
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200493 /* Update state. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200494 if ((ret = ctr_drbg_update_internal(ctx, seed)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100495 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200496 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200497 ctx->reseed_counter = 1;
498
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100499exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200500 mbedtls_platform_zeroize(seed, sizeof(seed));
501 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200502}
503
Jens Wiklander32b31802023-10-06 16:59:46 +0200504int mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context *ctx,
505 const unsigned char *additional, size_t len)
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200506{
Jens Wiklander32b31802023-10-06 16:59:46 +0200507 return mbedtls_ctr_drbg_reseed_internal(ctx, additional, len, 0);
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200508}
509
510/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
511 * is sufficient to achieve the maximum security strength given the key
512 * size and entropy length. If there is enough entropy in the initial
513 * call to the entropy function to serve as both the entropy input and
514 * the nonce, don't make a second call to get a nonce. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200515static size_t good_nonce_len(size_t entropy_len)
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200516{
Jens Wiklander32b31802023-10-06 16:59:46 +0200517 if (entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2) {
518 return 0;
519 } else {
520 return (entropy_len + 1) / 2;
521 }
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200522}
523
Jerome Forissier5b25c762020-04-07 11:18:49 +0200524/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
525 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
526 * implements
527 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
528 * security_strength) -> initial_working_state
529 * with inputs
530 * custom[:len] = nonce || personalization_string
531 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
532 * and with outputs
533 * ctx = initial_working_state
534 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200535int mbedtls_ctr_drbg_seed(mbedtls_ctr_drbg_context *ctx,
536 int (*f_entropy)(void *, unsigned char *, size_t),
537 void *p_entropy,
538 const unsigned char *custom,
539 size_t len)
Jerome Forissier5b25c762020-04-07 11:18:49 +0200540{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200541 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200542 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200543 size_t nonce_len;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200544
Jens Wiklander32b31802023-10-06 16:59:46 +0200545 memset(key, 0, MBEDTLS_CTR_DRBG_KEYSIZE);
Jerome Forissier5b25c762020-04-07 11:18:49 +0200546
Jerome Forissier79013242021-07-28 10:24:04 +0200547 /* The mutex is initialized iff f_entropy is set. */
548#if defined(MBEDTLS_THREADING_C)
Jens Wiklander32b31802023-10-06 16:59:46 +0200549 mbedtls_mutex_init(&ctx->mutex);
Jerome Forissier79013242021-07-28 10:24:04 +0200550#endif
551
Jerome Forissier5b25c762020-04-07 11:18:49 +0200552 ctx->f_entropy = f_entropy;
553 ctx->p_entropy = p_entropy;
554
Jens Wiklander32b31802023-10-06 16:59:46 +0200555 if (ctx->entropy_len == 0) {
Jerome Forissier5b25c762020-04-07 11:18:49 +0200556 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Jens Wiklander32b31802023-10-06 16:59:46 +0200557 }
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200558 /* ctx->reseed_counter contains the desired amount of entropy to
559 * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
560 * If it's -1, indicating that the entropy nonce length was not set
561 * explicitly, use a sufficiently large nonce for security. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200562 nonce_len = (ctx->reseed_counter >= 0 ?
563 (size_t) ctx->reseed_counter :
564 good_nonce_len(ctx->entropy_len));
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200565
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200566 /* Initialize with an empty key. */
Sungbae Yoo4d211f32024-11-19 02:47:55 +0000567#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
Tom Van Eyckb0563632024-06-13 16:20:14 +0200568 psa_status_t status;
569
570 status = ctr_drbg_setup_psa_context(&ctx->psa_ctx, key, MBEDTLS_CTR_DRBG_KEYSIZE);
571 if (status != PSA_SUCCESS) {
572 ret = psa_generic_status_to_mbedtls(status);
573 return status;
574 }
Sungbae Yoo4d211f32024-11-19 02:47:55 +0000575#else
576 if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, key,
577 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
578 return ret;
579 }
Tom Van Eyckb0563632024-06-13 16:20:14 +0200580#endif
Jerome Forissier5b25c762020-04-07 11:18:49 +0200581
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200582 /* Do the initial seeding. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200583 if ((ret = mbedtls_ctr_drbg_reseed_internal(ctx, custom, len,
584 nonce_len)) != 0) {
585 return ret;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200586 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200587 return 0;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200588}
589
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100590/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
591 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
592 * implements
593 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
594 * -> working_state_after_reseed
595 * if required, then
596 * CTR_DRBG_Generate(working_state_after_reseed,
597 * requested_number_of_bits, additional_input)
598 * -> status, returned_bits, new_working_state
599 * with inputs
600 * ctx contains working_state
601 * requested_number_of_bits = 8 * output_len
602 * additional[:add_len] = additional_input
603 * and entropy_input comes from calling ctx->f_entropy
604 * and with outputs
605 * status = SUCCESS (this function does the reseed internally)
606 * returned_bits = output[:output_len]
607 * ctx contains new_working_state
608 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200609int mbedtls_ctr_drbg_random_with_add(void *p_rng,
610 unsigned char *output, size_t output_len,
611 const unsigned char *additional, size_t add_len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200612{
613 int ret = 0;
614 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
Jens Wiklander817466c2018-05-22 13:49:31 +0200615 unsigned char *p = output;
Tom Van Eyckb0563632024-06-13 16:20:14 +0200616 struct {
617 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
618 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
619 } locals;
Jens Wiklander817466c2018-05-22 13:49:31 +0200620 size_t use_len;
621
Jens Wiklander32b31802023-10-06 16:59:46 +0200622 if (output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST) {
623 return MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG;
624 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200625
Jens Wiklander32b31802023-10-06 16:59:46 +0200626 if (add_len > MBEDTLS_CTR_DRBG_MAX_INPUT) {
627 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
628 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200629
Tom Van Eyckb0563632024-06-13 16:20:14 +0200630 memset(locals.add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN);
Jens Wiklander817466c2018-05-22 13:49:31 +0200631
Jens Wiklander32b31802023-10-06 16:59:46 +0200632 if (ctx->reseed_counter > ctx->reseed_interval ||
633 ctx->prediction_resistance) {
634 if ((ret = mbedtls_ctr_drbg_reseed(ctx, additional, add_len)) != 0) {
635 return ret;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100636 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200637 add_len = 0;
638 }
639
Jens Wiklander32b31802023-10-06 16:59:46 +0200640 if (add_len > 0) {
Tom Van Eyckb0563632024-06-13 16:20:14 +0200641 if ((ret = block_cipher_df(locals.add_input, additional, add_len)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100642 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200643 }
Tom Van Eyckb0563632024-06-13 16:20:14 +0200644 if ((ret = ctr_drbg_update_internal(ctx, locals.add_input)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100645 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200646 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200647 }
648
Jens Wiklander32b31802023-10-06 16:59:46 +0200649 while (output_len > 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200650 /*
Tom Van Eyckb0563632024-06-13 16:20:14 +0200651 * Increase counter (treat it as a 128-bit big-endian integer).
Jens Wiklander817466c2018-05-22 13:49:31 +0200652 */
Tom Van Eyckb0563632024-06-13 16:20:14 +0200653 mbedtls_ctr_increment_counter(ctx->counter);
Jens Wiklander817466c2018-05-22 13:49:31 +0200654
655 /*
656 * Crypt counter block
657 */
Sungbae Yoo4d211f32024-11-19 02:47:55 +0000658#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
Tom Van Eyckb0563632024-06-13 16:20:14 +0200659 psa_status_t status;
660 size_t tmp_len;
661
662 status = psa_cipher_update(&ctx->psa_ctx.operation, ctx->counter, sizeof(ctx->counter),
663 locals.tmp, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);
664 if (status != PSA_SUCCESS) {
665 ret = psa_generic_status_to_mbedtls(status);
666 goto exit;
667 }
Sungbae Yoo4d211f32024-11-19 02:47:55 +0000668#else
669 if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
670 ctx->counter, locals.tmp)) != 0) {
671 goto exit;
672 }
Tom Van Eyckb0563632024-06-13 16:20:14 +0200673#endif
Jens Wiklander817466c2018-05-22 13:49:31 +0200674
Jens Wiklander32b31802023-10-06 16:59:46 +0200675 use_len = (output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE)
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200676 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
Jens Wiklander817466c2018-05-22 13:49:31 +0200677 /*
678 * Copy random block to destination
679 */
Tom Van Eyckb0563632024-06-13 16:20:14 +0200680 memcpy(p, locals.tmp, use_len);
Jens Wiklander817466c2018-05-22 13:49:31 +0200681 p += use_len;
682 output_len -= use_len;
683 }
684
Tom Van Eyckb0563632024-06-13 16:20:14 +0200685 if ((ret = ctr_drbg_update_internal(ctx, locals.add_input)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100686 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200687 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200688
689 ctx->reseed_counter++;
690
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100691exit:
Tom Van Eyckb0563632024-06-13 16:20:14 +0200692 mbedtls_platform_zeroize(&locals, sizeof(locals));
Jens Wiklander32b31802023-10-06 16:59:46 +0200693 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200694}
695
Jens Wiklander32b31802023-10-06 16:59:46 +0200696int mbedtls_ctr_drbg_random(void *p_rng, unsigned char *output,
697 size_t output_len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200698{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200699 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200700 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
701
702#if defined(MBEDTLS_THREADING_C)
Jens Wiklander32b31802023-10-06 16:59:46 +0200703 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
704 return ret;
705 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200706#endif
707
Jens Wiklander32b31802023-10-06 16:59:46 +0200708 ret = mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, NULL, 0);
Jens Wiklander817466c2018-05-22 13:49:31 +0200709
710#if defined(MBEDTLS_THREADING_C)
Jens Wiklander32b31802023-10-06 16:59:46 +0200711 if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
712 return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
713 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200714#endif
715
Jens Wiklander32b31802023-10-06 16:59:46 +0200716 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200717}
718
719#if defined(MBEDTLS_FS_IO)
Jens Wiklander32b31802023-10-06 16:59:46 +0200720int mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context *ctx,
721 const char *path)
Jens Wiklander817466c2018-05-22 13:49:31 +0200722{
723 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
724 FILE *f;
Jens Wiklander32b31802023-10-06 16:59:46 +0200725 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT];
Jens Wiklander817466c2018-05-22 13:49:31 +0200726
Jens Wiklander32b31802023-10-06 16:59:46 +0200727 if ((f = fopen(path, "wb")) == NULL) {
728 return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200729 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200730
731 /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
732 mbedtls_setbuf(f, NULL);
733
734 if ((ret = mbedtls_ctr_drbg_random(ctx, buf,
735 MBEDTLS_CTR_DRBG_MAX_INPUT)) != 0) {
736 goto exit;
737 }
738
739 if (fwrite(buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f) !=
740 MBEDTLS_CTR_DRBG_MAX_INPUT) {
741 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
742 } else {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100743 ret = 0;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200744 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200745
746exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200747 mbedtls_platform_zeroize(buf, sizeof(buf));
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100748
Jens Wiklander32b31802023-10-06 16:59:46 +0200749 fclose(f);
750 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200751}
752
Jens Wiklander32b31802023-10-06 16:59:46 +0200753int mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context *ctx,
754 const char *path)
Jens Wiklander817466c2018-05-22 13:49:31 +0200755{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100756 int ret = 0;
757 FILE *f = NULL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200758 size_t n;
Jens Wiklander32b31802023-10-06 16:59:46 +0200759 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT];
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100760 unsigned char c;
Jens Wiklander817466c2018-05-22 13:49:31 +0200761
Jens Wiklander32b31802023-10-06 16:59:46 +0200762 if ((f = fopen(path, "rb")) == NULL) {
763 return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
764 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200765
Jens Wiklander32b31802023-10-06 16:59:46 +0200766 /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
767 mbedtls_setbuf(f, NULL);
768
769 n = fread(buf, 1, sizeof(buf), f);
770 if (fread(&c, 1, 1, f) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100771 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
772 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200773 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200774 if (n == 0 || ferror(f)) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100775 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
776 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200777 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200778 fclose(f);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100779 f = NULL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200780
Jens Wiklander32b31802023-10-06 16:59:46 +0200781 ret = mbedtls_ctr_drbg_update(ctx, buf, n);
Jens Wiklander817466c2018-05-22 13:49:31 +0200782
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100783exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200784 mbedtls_platform_zeroize(buf, sizeof(buf));
785 if (f != NULL) {
786 fclose(f);
787 }
788 if (ret != 0) {
789 return ret;
790 }
791 return mbedtls_ctr_drbg_write_seed_file(ctx, path);
Jens Wiklander817466c2018-05-22 13:49:31 +0200792}
793#endif /* MBEDTLS_FS_IO */
794
795#if defined(MBEDTLS_SELF_TEST)
796
Jerome Forissier79013242021-07-28 10:24:04 +0200797/* The CTR_DRBG NIST test vectors used here are available at
798 * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip
799 *
800 * The parameters used to derive the test data are:
801 *
802 * [AES-128 use df]
803 * [PredictionResistance = True/False]
804 * [EntropyInputLen = 128]
805 * [NonceLen = 64]
806 * [PersonalizationStringLen = 128]
807 * [AdditionalInputLen = 0]
808 * [ReturnedBitsLen = 512]
809 *
810 * [AES-256 use df]
811 * [PredictionResistance = True/False]
812 * [EntropyInputLen = 256]
813 * [NonceLen = 128]
814 * [PersonalizationStringLen = 256]
815 * [AdditionalInputLen = 0]
816 * [ReturnedBitsLen = 512]
817 *
818 */
Jens Wiklander817466c2018-05-22 13:49:31 +0200819
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200820#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
Jerome Forissier79013242021-07-28 10:24:04 +0200821static const unsigned char entropy_source_pr[] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200822{ 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb,
823 0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92,
824 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8,
825 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20,
826 0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0,
827 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad,
828 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 };
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200829
Jerome Forissier79013242021-07-28 10:24:04 +0200830static const unsigned char entropy_source_nopr[] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200831{ 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45,
832 0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9,
833 0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20,
834 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f,
835 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c };
Jerome Forissier79013242021-07-28 10:24:04 +0200836
837static const unsigned char pers_pr[] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200838{ 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a,
839 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad };
Jerome Forissier79013242021-07-28 10:24:04 +0200840
841static const unsigned char pers_nopr[] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200842{ 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c,
843 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f };
Jerome Forissier79013242021-07-28 10:24:04 +0200844
845static const unsigned char result_pr[] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200846{ 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66,
847 0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff,
848 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10,
849 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30,
850 0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4,
851 0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc,
852 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06,
853 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf };
Jerome Forissier79013242021-07-28 10:24:04 +0200854
855static const unsigned char result_nopr[] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200856{ 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13,
857 0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0,
858 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf,
859 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2,
860 0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7,
861 0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2,
862 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02,
863 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 };
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200864#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Jens Wiklander817466c2018-05-22 13:49:31 +0200865
Jerome Forissier79013242021-07-28 10:24:04 +0200866static const unsigned char entropy_source_pr[] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200867{ 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49,
868 0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a,
869 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85,
870 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e,
871 0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15,
872 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45,
873 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8,
874 0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c,
875 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3,
876 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce,
877 0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e,
878 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76,
879 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77,
880 0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe };
Jerome Forissier79013242021-07-28 10:24:04 +0200881
882static const unsigned char entropy_source_nopr[] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200883{ 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d,
884 0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0,
885 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73,
886 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c,
887 0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2,
888 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1,
889 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a,
890 0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb,
891 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a,
892 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 };
Jerome Forissier79013242021-07-28 10:24:04 +0200893
894static const unsigned char pers_pr[] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200895{ 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33,
896 0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e,
897 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0,
898 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 };
Jerome Forissier79013242021-07-28 10:24:04 +0200899
900static const unsigned char pers_nopr[] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200901{ 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29,
902 0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf,
903 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb,
904 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b };
Jerome Forissier79013242021-07-28 10:24:04 +0200905
906static const unsigned char result_pr[] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200907{ 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85,
908 0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d,
909 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62,
910 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d,
911 0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb,
912 0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39,
913 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40,
914 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 };
Jerome Forissier79013242021-07-28 10:24:04 +0200915
916static const unsigned char result_nopr[] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200917{ 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad,
918 0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3,
919 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b,
920 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14,
921 0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54,
922 0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30,
923 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a,
924 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 };
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200925#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Jens Wiklander817466c2018-05-22 13:49:31 +0200926
927static size_t test_offset;
Jens Wiklander32b31802023-10-06 16:59:46 +0200928static int ctr_drbg_self_test_entropy(void *data, unsigned char *buf,
929 size_t len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200930{
931 const unsigned char *p = data;
Jens Wiklander32b31802023-10-06 16:59:46 +0200932 memcpy(buf, p + test_offset, len);
Jens Wiklander817466c2018-05-22 13:49:31 +0200933 test_offset += len;
Jens Wiklander32b31802023-10-06 16:59:46 +0200934 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200935}
936
Jens Wiklander32b31802023-10-06 16:59:46 +0200937#define CHK(c) if ((c) != 0) \
938 { \
939 if (verbose != 0) \
940 mbedtls_printf("failed\n"); \
941 return 1; \
942 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200943
Jerome Forissier039e02d2022-08-09 17:10:15 +0200944#define SELF_TEST_OUTPUT_DISCARD_LENGTH 64
Jerome Forissier79013242021-07-28 10:24:04 +0200945
Jens Wiklander817466c2018-05-22 13:49:31 +0200946/*
947 * Checkup routine
948 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200949int mbedtls_ctr_drbg_self_test(int verbose)
Jens Wiklander817466c2018-05-22 13:49:31 +0200950{
951 mbedtls_ctr_drbg_context ctx;
Jens Wiklander32b31802023-10-06 16:59:46 +0200952 unsigned char buf[sizeof(result_pr)];
Jens Wiklander817466c2018-05-22 13:49:31 +0200953
Jens Wiklander32b31802023-10-06 16:59:46 +0200954 mbedtls_ctr_drbg_init(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200955
956 /*
957 * Based on a NIST CTR_DRBG test vector (PR = True)
958 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200959 if (verbose != 0) {
960 mbedtls_printf(" CTR_DRBG (PR = TRUE) : ");
961 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200962
963 test_offset = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +0200964 mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
965 mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2);
966 CHK(mbedtls_ctr_drbg_seed(&ctx,
967 ctr_drbg_self_test_entropy,
968 (void *) entropy_source_pr,
969 pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE));
970 mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_ON);
971 CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH));
972 CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_pr)));
973 CHK(memcmp(buf, result_pr, sizeof(result_pr)));
Jens Wiklander817466c2018-05-22 13:49:31 +0200974
Jens Wiklander32b31802023-10-06 16:59:46 +0200975 mbedtls_ctr_drbg_free(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200976
Jens Wiklander32b31802023-10-06 16:59:46 +0200977 if (verbose != 0) {
978 mbedtls_printf("passed\n");
979 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200980
981 /*
982 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
983 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200984 if (verbose != 0) {
985 mbedtls_printf(" CTR_DRBG (PR = FALSE): ");
986 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200987
Jens Wiklander32b31802023-10-06 16:59:46 +0200988 mbedtls_ctr_drbg_init(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200989
990 test_offset = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +0200991 mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
992 mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2);
993 CHK(mbedtls_ctr_drbg_seed(&ctx,
994 ctr_drbg_self_test_entropy,
995 (void *) entropy_source_nopr,
996 pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE));
997 CHK(mbedtls_ctr_drbg_reseed(&ctx, NULL, 0));
998 CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH));
999 CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_nopr)));
1000 CHK(memcmp(buf, result_nopr, sizeof(result_nopr)));
Jens Wiklander817466c2018-05-22 13:49:31 +02001001
Jens Wiklander32b31802023-10-06 16:59:46 +02001002 mbedtls_ctr_drbg_free(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +02001003
Jens Wiklander32b31802023-10-06 16:59:46 +02001004 if (verbose != 0) {
1005 mbedtls_printf("passed\n");
1006 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001007
Jens Wiklander32b31802023-10-06 16:59:46 +02001008 if (verbose != 0) {
1009 mbedtls_printf("\n");
1010 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001011
Jens Wiklander32b31802023-10-06 16:59:46 +02001012 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +02001013}
1014#endif /* MBEDTLS_SELF_TEST */
1015
1016#endif /* MBEDTLS_CTR_DRBG_C */