blob: 66d9d28c589a621b6b37e2734199f721962df6f6 [file] [log] [blame]
Paul Bakker0e04d0e2011-11-27 14:46:59 +00001/*
2 * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Dave Rodgman16799db2023-11-02 19:47:20 +00005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Paul Bakker0e04d0e2011-11-27 14:46:59 +00006 */
7/*
Paul Sokolovsky8d6d8c82018-02-10 11:11:41 +02008 * The NIST SP 800-90 DRBGs are described in the following publication.
Paul Bakker0e04d0e2011-11-27 14:46:59 +00009 *
Tom Cosgrovece37c5e2023-08-04 13:53:36 +010010 * https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-90r.pdf
Paul Bakker0e04d0e2011-11-27 14:46:59 +000011 */
12
Gilles Peskinedb09ef62020-06-03 01:43:33 +020013#include "common.h"
Paul Bakker0e04d0e2011-11-27 14:46:59 +000014
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020015#if defined(MBEDTLS_CTR_DRBG_C)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000016
Dave Rodgman591ff052024-01-13 16:42:38 +000017#include "ctr.h"
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000018#include "mbedtls/ctr_drbg.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050019#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000020#include "mbedtls/error.h"
Paul Bakker0e04d0e2011-11-27 14:46:59 +000021
Rich Evans00ab4702015-02-06 13:43:58 +000022#include <string.h>
23
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020024#if defined(MBEDTLS_FS_IO)
Paul Bakkerfc754a92011-12-05 13:23:51 +000025#include <stdio.h>
26#endif
27
Valerio Setti5f4b28d2023-11-13 10:18:16 +010028/* Using error translation functions from PSA to MbedTLS */
29#if !defined(MBEDTLS_AES_C)
30#include "psa_util_internal.h"
31#endif
32
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000033#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010034
Valerio Setti5f4b28d2023-11-13 10:18:16 +010035#if !defined(MBEDTLS_AES_C)
36static 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
Paul Bakker18d32912011-12-10 21:42:49 +000070/*
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020071 * CTR_DRBG context initialization
72 */
Gilles Peskine449bd832023-01-11 14:50:10 +010073void mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context *ctx)
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020074{
Gilles Peskine449bd832023-01-11 14:50:10 +010075 memset(ctx, 0, sizeof(mbedtls_ctr_drbg_context));
Valerio Setti5f4b28d2023-11-13 10:18:16 +010076#if defined(MBEDTLS_AES_C)
Gilles Peskine449bd832023-01-11 14:50:10 +010077 mbedtls_aes_init(&ctx->aes_ctx);
Valerio Setti5f4b28d2023-11-13 10:18:16 +010078#else
79 ctx->psa_ctx.key_id = MBEDTLS_SVC_KEY_ID_INIT;
80 ctx->psa_ctx.operation = psa_cipher_operation_init();
81#endif
Gilles Peskinee9a34542019-10-22 20:43:24 +020082 /* Indicate that the entropy nonce length is not set explicitly.
83 * See mbedtls_ctr_drbg_set_nonce_len(). */
84 ctx->reseed_counter = -1;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010085
Gavin Acquroff6aceb512020-03-01 17:06:11 -080086 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020087}
88
Gavin Acquroff6aceb512020-03-01 17:06:11 -080089/*
90 * This function resets CTR_DRBG context to the state immediately
91 * after initial call of mbedtls_ctr_drbg_init().
92 */
Gilles Peskine449bd832023-01-11 14:50:10 +010093void mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context *ctx)
Paul Bakkerfff03662014-06-18 16:21:25 +020094{
Gilles Peskine449bd832023-01-11 14:50:10 +010095 if (ctx == NULL) {
Paul Bakkerfff03662014-06-18 16:21:25 +020096 return;
Gilles Peskine449bd832023-01-11 14:50:10 +010097 }
Paul Bakkerfff03662014-06-18 16:21:25 +020098
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010099#if defined(MBEDTLS_THREADING_C)
Gilles Peskineda290f92021-02-09 18:44:02 +0100100 /* The mutex is initialized iff f_entropy is set. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100101 if (ctx->f_entropy != NULL) {
102 mbedtls_mutex_free(&ctx->mutex);
103 }
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100104#endif
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100105#if defined(MBEDTLS_AES_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100106 mbedtls_aes_free(&ctx->aes_ctx);
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100107#else
108 ctr_drbg_destroy_psa_contex(&ctx->psa_ctx);
109#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100110 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ctr_drbg_context));
Gavin Acquroff6aceb512020-03-01 17:06:11 -0800111 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
112 ctx->reseed_counter = -1;
Paul Bakkerfff03662014-06-18 16:21:25 +0200113}
114
Gilles Peskine449bd832023-01-11 14:50:10 +0100115void mbedtls_ctr_drbg_set_prediction_resistance(mbedtls_ctr_drbg_context *ctx,
116 int resistance)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000117{
118 ctx->prediction_resistance = resistance;
119}
120
Gilles Peskine449bd832023-01-11 14:50:10 +0100121void mbedtls_ctr_drbg_set_entropy_len(mbedtls_ctr_drbg_context *ctx,
122 size_t len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000123{
124 ctx->entropy_len = len;
125}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200126
Gilles Peskine449bd832023-01-11 14:50:10 +0100127int mbedtls_ctr_drbg_set_nonce_len(mbedtls_ctr_drbg_context *ctx,
128 size_t len)
Gilles Peskine9be50982019-10-22 18:42:27 +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. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100132 if (ctx->f_entropy != NULL) {
133 return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
134 }
Gilles Peskine9be50982019-10-22 18:42:27 +0200135
Gilles Peskine449bd832023-01-11 14:50:10 +0100136 if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
137 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
138 }
Dave Rodgman4a5c9ee2023-02-10 16:03:44 +0000139
Gilles Peskine9be50982019-10-22 18:42:27 +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. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100143 if (len > INT_MAX) {
144 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
145 }
Gilles Peskine9be50982019-10-22 18:42:27 +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;
Gilles Peskine449bd832023-01-11 14:50:10 +0100152 return 0;
Gilles Peskine9be50982019-10-22 18:42:27 +0200153}
154
Gilles Peskine449bd832023-01-11 14:50:10 +0100155void mbedtls_ctr_drbg_set_reseed_interval(mbedtls_ctr_drbg_context *ctx,
156 int interval)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000157{
158 ctx->reseed_interval = interval;
159}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200160
Gilles Peskine449bd832023-01-11 14:50:10 +0100161static int block_cipher_df(unsigned char *output,
162 const unsigned char *data, size_t data_len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000163{
Hanno Beckera08651f2018-10-05 09:38:59 +0100164 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
165 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12: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];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100169 unsigned char *p, *iv;
Dvir Markovich1b364992017-06-26 13:43:34 +0300170 int ret = 0;
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100171#if defined(MBEDTLS_AES_C)
172 mbedtls_aes_context aes_ctx;
173#else
174 psa_status_t status;
175 size_t tmp_len;
176 mbedtls_ctr_drbg_psa_context psa_ctx;
177
178 psa_ctx.key_id = MBEDTLS_SVC_KEY_ID_INIT;
179 psa_ctx.operation = psa_cipher_operation_init();
180#endif
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000181
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200182 int i, j;
183 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000184
Gilles Peskine449bd832023-01-11 14:50:10 +0100185 if (data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
186 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
187 }
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100188
Gilles Peskine449bd832023-01-11 14:50:10 +0100189 memset(buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
190 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000191
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 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200199 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Gilles Peskine449bd832023-01-11 14:50:10 +0100200 MBEDTLS_PUT_UINT32_BE(data_len, p, 0);
Joe Subbiania5cb0d22021-08-23 11:35:25 +0100201 p += 4 + 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200202 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Gilles Peskine449bd832023-01-11 14:50:10 +0100203 memcpy(p, data, data_len);
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000204 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000205
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200206 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000207
Gilles Peskine449bd832023-01-11 14:50:10 +0100208 for (i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000209 key[i] = i;
Gilles Peskine449bd832023-01-11 14:50:10 +0100210 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000211
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100212#if defined(MBEDTLS_AES_C)
213 mbedtls_aes_init(&aes_ctx);
214
Gilles Peskine449bd832023-01-11 14:50:10 +0100215 if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, key,
216 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300217 goto exit;
218 }
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100219#else
220 status = ctr_drbg_setup_psa_context(&psa_ctx, key, sizeof(key));
221 if (status != PSA_SUCCESS) {
222 ret = psa_generic_status_to_mbedtls(status);
223 goto exit;
224 }
225#endif
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000226
227 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200228 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000229 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100230 for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000231 p = buf;
Gilles Peskine449bd832023-01-11 14:50:10 +0100232 memset(chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000233 use_len = buf_len;
234
Gilles Peskine449bd832023-01-11 14:50:10 +0100235 while (use_len > 0) {
236 mbedtls_xor(chain, chain, p, MBEDTLS_CTR_DRBG_BLOCKSIZE);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200237 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Gilles Peskine449bd832023-01-11 14:50:10 +0100238 use_len -= (use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE) ?
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200239 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000240
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100241#if defined(MBEDTLS_AES_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100242 if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,
243 chain, chain)) != 0) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300244 goto exit;
245 }
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100246#else
247 status = psa_cipher_update(&psa_ctx.operation, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE,
248 chain, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);
249 if (status != PSA_SUCCESS) {
250 ret = psa_generic_status_to_mbedtls(status);
251 goto exit;
252 }
253#endif
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000254 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200255
Gilles Peskine449bd832023-01-11 14:50:10 +0100256 memcpy(tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000257
258 /*
259 * Update IV
260 */
261 buf[3]++;
262 }
263
264 /*
265 * Do final encryption with reduced data
266 */
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100267#if defined(MBEDTLS_AES_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100268 if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, tmp,
269 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300270 goto exit;
271 }
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100272#else
273 ctr_drbg_destroy_psa_contex(&psa_ctx);
274
275 status = ctr_drbg_setup_psa_context(&psa_ctx, tmp, MBEDTLS_CTR_DRBG_KEYSIZE);
276 if (status != PSA_SUCCESS) {
277 ret = psa_generic_status_to_mbedtls(status);
278 goto exit;
279 }
280#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200281 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000282 p = output;
283
Gilles Peskine449bd832023-01-11 14:50:10 +0100284 for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100285#if defined(MBEDTLS_AES_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100286 if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,
287 iv, iv)) != 0) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300288 goto exit;
289 }
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100290#else
291 status = psa_cipher_update(&psa_ctx.operation, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE,
292 iv, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);
293 if (status != PSA_SUCCESS) {
294 ret = psa_generic_status_to_mbedtls(status);
295 goto exit;
296 }
297#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100298 memcpy(p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200299 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000300 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300301exit:
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100302#if defined(MBEDTLS_AES_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100303 mbedtls_aes_free(&aes_ctx);
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100304#else
305 ctr_drbg_destroy_psa_contex(&psa_ctx);
306#endif
Dvir Markovich1b364992017-06-26 13:43:34 +0300307 /*
Gilles Peskine449bd832023-01-11 14:50:10 +0100308 * 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) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300315 /*
Gilles Peskine449bd832023-01-11 14:50:10 +0100316 * wipe partial seed from memory
317 */
318 mbedtls_platform_zeroize(output, MBEDTLS_CTR_DRBG_SEEDLEN);
Dvir Markovich1b364992017-06-26 13:43:34 +0300319 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200320
Gilles Peskine449bd832023-01-11 14:50:10 +0100321 return ret;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000322}
323
Gilles Peskineed7da592018-08-03 20:16:52 +0200324/* 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 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100332static int ctr_drbg_update_internal(mbedtls_ctr_drbg_context *ctx,
333 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN])
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000334{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200335 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000336 unsigned char *p = tmp;
Dave Rodgman591ff052024-01-13 16:42:38 +0000337 int j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300338 int ret = 0;
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100339#if !defined(MBEDTLS_AES_C)
340 psa_status_t status;
341 size_t tmp_len;
342#endif
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000343
Gilles Peskine449bd832023-01-11 14:50:10 +0100344 memset(tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000345
Gilles Peskine449bd832023-01-11 14:50:10 +0100346 for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000347 /*
348 * Increase counter
349 */
Dave Rodgman591ff052024-01-13 16:42:38 +0000350 mbedtls_ctr_increment_counter(ctx->counter);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000351
352 /*
353 * Crypt counter block
354 */
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100355#if defined(MBEDTLS_AES_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100356 if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
357 ctx->counter, p)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200358 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300359 }
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100360#else
361 status = psa_cipher_update(&ctx->psa_ctx.operation, ctx->counter, sizeof(ctx->counter),
362 p, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);
363 if (status != PSA_SUCCESS) {
364 ret = psa_generic_status_to_mbedtls(status);
365 goto exit;
366 }
367#endif
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000368
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200369 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000370 }
371
Dave Rodgman174eeff2024-01-13 16:43:18 +0000372 mbedtls_xor(tmp, tmp, data, MBEDTLS_CTR_DRBG_SEEDLEN);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000373
374 /*
375 * Update key and counter
376 */
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100377#if defined(MBEDTLS_AES_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100378 if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, tmp,
379 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200380 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300381 }
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100382#else
383 ctr_drbg_destroy_psa_contex(&ctx->psa_ctx);
384
385 status = ctr_drbg_setup_psa_context(&ctx->psa_ctx, tmp, MBEDTLS_CTR_DRBG_KEYSIZE);
386 if (status != PSA_SUCCESS) {
387 ret = psa_generic_status_to_mbedtls(status);
388 goto exit;
389 }
390#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100391 memcpy(ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
392 MBEDTLS_CTR_DRBG_BLOCKSIZE);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000393
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200394exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100395 mbedtls_platform_zeroize(tmp, sizeof(tmp));
396 return ret;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000397}
398
Gilles Peskineed7da592018-08-03 20:16:52 +0200399/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
TRodziewicz26371e42021-06-08 16:45:41 +0200400 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
Gilles Peskineed7da592018-08-03 20:16:52 +0200401 * 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 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100411int mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context *ctx,
412 const unsigned char *additional,
413 size_t add_len)
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000414{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200415 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Janos Follath24eed8d2019-11-22 13:21:35 +0000416 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000417
Gilles Peskine449bd832023-01-11 14:50:10 +0100418 if (add_len == 0) {
419 return 0;
420 }
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100421
Gilles Peskine449bd832023-01-11 14:50:10 +0100422 if ((ret = block_cipher_df(add_input, additional, add_len)) != 0) {
Gilles Peskined9199932018-09-11 16:41:54 +0200423 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100424 }
425 if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {
Gilles Peskined9199932018-09-11 16:41:54 +0200426 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100427 }
Gilles Peskined9199932018-09-11 16:41:54 +0200428
429exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100430 mbedtls_platform_zeroize(add_input, sizeof(add_input));
431 return ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000432}
433
Gilles Peskineed7da592018-08-03 20:16:52 +0200434/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
Gilles Peskine9be50982019-10-22 18:42:27 +0200435 * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
Gilles Peskineed7da592018-08-03 20:16:52 +0200436 * 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
Gilles Peskine9be50982019-10-22 18:42:27 +0200443 * for (ctx->entropy_len + nonce_len) bytes
Gilles Peskineed7da592018-08-03 20:16:52 +0200444 * and with output
445 * ctx contains new_working_state
446 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100447static 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)
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000451{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200452 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000453 size_t seedlen = 0;
Janos Follath24eed8d2019-11-22 13:21:35 +0000454 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000455
Gilles Peskine449bd832023-01-11 14:50:10 +0100456 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 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000465
Gilles Peskine449bd832023-01-11 14:50:10 +0100466 memset(seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT);
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000467
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200468 /* Gather entropy_len bytes of entropy to seed state. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100469 if (0 != ctx->f_entropy(ctx->p_entropy, seed, ctx->entropy_len)) {
470 return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000471 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000472 seedlen += ctx->entropy_len;
473
Gilles Peskine9be50982019-10-22 18:42:27 +0200474 /* Gather entropy for a nonce if requested. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100475 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;
Gilles Peskine9be50982019-10-22 18:42:27 +0200478 }
479 seedlen += nonce_len;
480 }
481
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200482 /* Add additional data if provided. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100483 if (additional != NULL && len != 0) {
484 memcpy(seed + seedlen, additional, len);
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000485 seedlen += len;
486 }
487
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200488 /* Reduce to 384 bits. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100489 if ((ret = block_cipher_df(seed, seed, seedlen)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200490 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100491 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000492
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200493 /* Update state. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100494 if ((ret = ctr_drbg_update_internal(ctx, seed)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200495 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100496 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000497 ctx->reseed_counter = 1;
498
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200499exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100500 mbedtls_platform_zeroize(seed, sizeof(seed));
501 return ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000502}
Paul Bakker9af723c2014-05-01 13:03:14 +0200503
Gilles Peskine449bd832023-01-11 14:50:10 +0100504int mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context *ctx,
505 const unsigned char *additional, size_t len)
Gilles Peskine9be50982019-10-22 18:42:27 +0200506{
Gilles Peskine449bd832023-01-11 14:50:10 +0100507 return mbedtls_ctr_drbg_reseed_internal(ctx, additional, len, 0);
Gilles Peskine9be50982019-10-22 18:42:27 +0200508}
509
Gilles Peskinee9a34542019-10-22 20:43:24 +0200510/* 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. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100515static size_t good_nonce_len(size_t entropy_len)
Gilles Peskinee9a34542019-10-22 20:43:24 +0200516{
Gilles Peskine449bd832023-01-11 14:50:10 +0100517 if (entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2) {
518 return 0;
519 } else {
520 return (entropy_len + 1) / 2;
521 }
Gilles Peskinee9a34542019-10-22 20:43:24 +0200522}
523
Gilles Peskine8bf56132019-10-02 20:31:54 +0200524/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
Gilles Peskine379561f2019-10-18 16:57:48 +0200525 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
Gilles Peskine8bf56132019-10-02 20:31:54 +0200526 * 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
Gilles Peskine379561f2019-10-18 16:57:48 +0200531 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
Gilles Peskine8bf56132019-10-02 20:31:54 +0200532 * and with outputs
533 * ctx = initial_working_state
534 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100535int 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)
Gilles Peskine8bf56132019-10-02 20:31:54 +0200540{
Janos Follath24eed8d2019-11-22 13:21:35 +0000541 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200542 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Gilles Peskinee9a34542019-10-22 20:43:24 +0200543 size_t nonce_len;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200544
Gilles Peskine449bd832023-01-11 14:50:10 +0100545 memset(key, 0, MBEDTLS_CTR_DRBG_KEYSIZE);
Gilles Peskine8bf56132019-10-02 20:31:54 +0200546
Gilles Peskineda290f92021-02-09 18:44:02 +0100547 /* The mutex is initialized iff f_entropy is set. */
Gilles Peskinef4b34292021-01-30 13:05:32 +0100548#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100549 mbedtls_mutex_init(&ctx->mutex);
Gilles Peskinef4b34292021-01-30 13:05:32 +0100550#endif
551
Gilles Peskine8bf56132019-10-02 20:31:54 +0200552 ctx->f_entropy = f_entropy;
553 ctx->p_entropy = p_entropy;
554
Gilles Peskine449bd832023-01-11 14:50:10 +0100555 if (ctx->entropy_len == 0) {
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200556 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskine449bd832023-01-11 14:50:10 +0100557 }
Gilles Peskinee9a34542019-10-22 20:43:24 +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. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100562 nonce_len = (ctx->reseed_counter >= 0 ?
563 (size_t) ctx->reseed_counter :
564 good_nonce_len(ctx->entropy_len));
Gilles Peskinee9a34542019-10-22 20:43:24 +0200565
Gilles Peskine9be50982019-10-22 18:42:27 +0200566 /* Initialize with an empty key. */
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100567#if defined(MBEDTLS_AES_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100568 if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, key,
569 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
570 return ret;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200571 }
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100572#else
573 psa_status_t status;
574
575 status = ctr_drbg_setup_psa_context(&ctx->psa_ctx, key, MBEDTLS_CTR_DRBG_KEYSIZE);
576 if (status != PSA_SUCCESS) {
577 ret = psa_generic_status_to_mbedtls(status);
578 return status;
579 }
580#endif
Gilles Peskine8bf56132019-10-02 20:31:54 +0200581
Gilles Peskinee9a34542019-10-22 20:43:24 +0200582 /* Do the initial seeding. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100583 if ((ret = mbedtls_ctr_drbg_reseed_internal(ctx, custom, len,
584 nonce_len)) != 0) {
585 return ret;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200586 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100587 return 0;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200588}
589
Gilles Peskineed7da592018-08-03 20:16:52 +0200590/* 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 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100609int 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)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000612{
613 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200614 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000615 unsigned char *p = output;
Dave Rodgman174eeff2024-01-13 16:43:18 +0000616 struct {
617 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
618 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
619 } locals;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000620 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000621
Gilles Peskine449bd832023-01-11 14:50:10 +0100622 if (output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST) {
623 return MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG;
624 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000625
Gilles Peskine449bd832023-01-11 14:50:10 +0100626 if (add_len > MBEDTLS_CTR_DRBG_MAX_INPUT) {
627 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
628 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000629
Dave Rodgman174eeff2024-01-13 16:43:18 +0000630 memset(locals.add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000631
Gilles Peskine449bd832023-01-11 14:50:10 +0100632 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;
Dvir Markovich1b364992017-06-26 13:43:34 +0300636 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000637 add_len = 0;
638 }
639
Gilles Peskine449bd832023-01-11 14:50:10 +0100640 if (add_len > 0) {
Dave Rodgman174eeff2024-01-13 16:43:18 +0000641 if ((ret = block_cipher_df(locals.add_input, additional, add_len)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200642 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100643 }
Dave Rodgman174eeff2024-01-13 16:43:18 +0000644 if ((ret = ctr_drbg_update_internal(ctx, locals.add_input)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200645 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100646 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000647 }
648
Gilles Peskine449bd832023-01-11 14:50:10 +0100649 while (output_len > 0) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000650 /*
Dave Rodgman591ff052024-01-13 16:42:38 +0000651 * Increase counter (treat it as a 128-bit big-endian integer).
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000652 */
Dave Rodgman591ff052024-01-13 16:42:38 +0000653 mbedtls_ctr_increment_counter(ctx->counter);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000654
655 /*
656 * Crypt counter block
657 */
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100658#if defined(MBEDTLS_AES_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100659 if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
Dave Rodgman174eeff2024-01-13 16:43:18 +0000660 ctx->counter, locals.tmp)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200661 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300662 }
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100663#else
664 psa_status_t status;
665 size_t tmp_len;
666
667 status = psa_cipher_update(&ctx->psa_ctx.operation, ctx->counter, sizeof(ctx->counter),
Dave Rodgman7e5b7f92024-01-16 17:28:25 +0000668 locals.tmp, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100669 if (status != PSA_SUCCESS) {
670 ret = psa_generic_status_to_mbedtls(status);
671 goto exit;
672 }
673#endif
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000674
Gilles Peskine449bd832023-01-11 14:50:10 +0100675 use_len = (output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE)
Hanno Beckera08651f2018-10-05 09:38:59 +0100676 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000677 /*
678 * Copy random block to destination
679 */
Dave Rodgman174eeff2024-01-13 16:43:18 +0000680 memcpy(p, locals.tmp, use_len);
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000681 p += use_len;
682 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000683 }
684
Dave Rodgman174eeff2024-01-13 16:43:18 +0000685 if ((ret = ctr_drbg_update_internal(ctx, locals.add_input)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200686 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100687 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000688
689 ctx->reseed_counter++;
690
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200691exit:
Dave Rodgman174eeff2024-01-13 16:43:18 +0000692 mbedtls_platform_zeroize(&locals, sizeof(locals));
Gilles Peskine449bd832023-01-11 14:50:10 +0100693 return ret;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000694}
695
Gilles Peskine449bd832023-01-11 14:50:10 +0100696int mbedtls_ctr_drbg_random(void *p_rng, unsigned char *output,
697 size_t output_len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000698{
Janos Follath24eed8d2019-11-22 13:21:35 +0000699 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100700 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
701
702#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100703 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
704 return ret;
705 }
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100706#endif
707
Gilles Peskine449bd832023-01-11 14:50:10 +0100708 ret = mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, NULL, 0);
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100709
710#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100711 if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
712 return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
713 }
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100714#endif
715
Gilles Peskine449bd832023-01-11 14:50:10 +0100716 return ret;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000717}
718
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200719#if defined(MBEDTLS_FS_IO)
Gilles Peskine449bd832023-01-11 14:50:10 +0100720int mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context *ctx,
721 const char *path)
Paul Bakkerfc754a92011-12-05 13:23:51 +0000722{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200723 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000724 FILE *f;
Gilles Peskine449bd832023-01-11 14:50:10 +0100725 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000726
Gilles Peskine449bd832023-01-11 14:50:10 +0100727 if ((f = fopen(path, "wb")) == NULL) {
728 return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
729 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000730
Gilles Peskineda0913b2022-06-30 17:03:40 +0200731 /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100732 mbedtls_setbuf(f, NULL);
Gilles Peskineda0913b2022-06-30 17:03:40 +0200733
Gilles Peskine449bd832023-01-11 14:50:10 +0100734 if ((ret = mbedtls_ctr_drbg_random(ctx, buf,
735 MBEDTLS_CTR_DRBG_MAX_INPUT)) != 0) {
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200736 goto exit;
Hanno Beckera08651f2018-10-05 09:38:59 +0100737 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100738
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 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100743 ret = 0;
Hanno Beckera08651f2018-10-05 09:38:59 +0100744 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000745
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100746exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100747 mbedtls_platform_zeroize(buf, sizeof(buf));
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200748
Gilles Peskine449bd832023-01-11 14:50:10 +0100749 fclose(f);
750 return ret;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000751}
752
Gilles Peskine449bd832023-01-11 14:50:10 +0100753int mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context *ctx,
754 const char *path)
Paul Bakkerfc754a92011-12-05 13:23:51 +0000755{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100756 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200757 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000758 size_t n;
Gilles Peskine449bd832023-01-11 14:50:10 +0100759 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT];
Gilles Peskine82204662018-09-11 18:43:09 +0200760 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000761
Gilles Peskine449bd832023-01-11 14:50:10 +0100762 if ((f = fopen(path, "rb")) == NULL) {
763 return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
764 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000765
Gilles Peskineda0913b2022-06-30 17:03:40 +0200766 /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100767 mbedtls_setbuf(f, NULL);
Gilles Peskineda0913b2022-06-30 17:03:40 +0200768
Gilles Peskine449bd832023-01-11 14:50:10 +0100769 n = fread(buf, 1, sizeof(buf), f);
770 if (fread(&c, 1, 1, f) != 0) {
Gilles Peskine82204662018-09-11 18:43:09 +0200771 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
772 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100773 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100774 if (n == 0 || ferror(f)) {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100775 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200776 goto exit;
777 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100778 fclose(f);
Gilles Peskine82204662018-09-11 18:43:09 +0200779 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200780
Gilles Peskine449bd832023-01-11 14:50:10 +0100781 ret = mbedtls_ctr_drbg_update(ctx, buf, n);
Gilles Peskine82204662018-09-11 18:43:09 +0200782
783exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100784 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);
Paul Bakkerfc754a92011-12-05 13:23:51 +0000792}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200793#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000794
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200795#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000796
ENT\stroej170f63d02020-12-28 08:50:23 -0600797/* 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 */
819
Gilles Peskine02e79a42019-10-07 17:06:06 +0200820#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
ENT\stroej1df307002020-12-26 12:41:04 -0600821static const unsigned char entropy_source_pr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100822{ 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 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200829
ENT\stroej1df307002020-12-26 12:41:04 -0600830static const unsigned char entropy_source_nopr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100831{ 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 };
ENT\stroej1df307002020-12-26 12:41:04 -0600836
stroebeljcd4de1b52021-01-04 18:14:32 -0600837static const unsigned char pers_pr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100838{ 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a,
839 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad };
ENT\stroej1df307002020-12-26 12:41:04 -0600840
stroebeljcd4de1b52021-01-04 18:14:32 -0600841static const unsigned char pers_nopr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100842{ 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c,
843 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f };
ENT\stroej1df307002020-12-26 12:41:04 -0600844
845static const unsigned char result_pr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100846{ 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 };
ENT\stroej1df307002020-12-26 12:41:04 -0600854
855static const unsigned char result_nopr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100856{ 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 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200864#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000865
ENT\stroej1df307002020-12-26 12:41:04 -0600866static const unsigned char entropy_source_pr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100867{ 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 };
ENT\stroej1df307002020-12-26 12:41:04 -0600881
882static const unsigned char entropy_source_nopr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100883{ 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 };
ENT\stroej1df307002020-12-26 12:41:04 -0600893
stroebeljcd4de1b52021-01-04 18:14:32 -0600894static const unsigned char pers_pr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100895{ 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 };
ENT\stroej1df307002020-12-26 12:41:04 -0600899
stroebeljcd4de1b52021-01-04 18:14:32 -0600900static const unsigned char pers_nopr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100901{ 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 };
ENT\stroej1df307002020-12-26 12:41:04 -0600905
906static const unsigned char result_pr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100907{ 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 };
ENT\stroej1df307002020-12-26 12:41:04 -0600915
916static const unsigned char result_nopr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100917{ 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 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200925#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000926
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100927static size_t test_offset;
Gilles Peskine449bd832023-01-11 14:50:10 +0100928static int ctr_drbg_self_test_entropy(void *data, unsigned char *buf,
929 size_t len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000930{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100931 const unsigned char *p = data;
Gilles Peskine449bd832023-01-11 14:50:10 +0100932 memcpy(buf, p + test_offset, len);
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100933 test_offset += len;
Gilles Peskine449bd832023-01-11 14:50:10 +0100934 return 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000935}
936
Gilles Peskine449bd832023-01-11 14:50:10 +0100937#define CHK(c) if ((c) != 0) \
938 { \
939 if (verbose != 0) \
940 mbedtls_printf("failed\n"); \
941 return 1; \
942 }
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100943
bootstrap-prime6dbbf442022-05-17 19:30:44 -0400944#define SELF_TEST_OUTPUT_DISCARD_LENGTH 64
stroebeljcd4de1b52021-01-04 18:14:32 -0600945
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000946/*
947 * Checkup routine
948 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100949int mbedtls_ctr_drbg_self_test(int verbose)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000950{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200951 mbedtls_ctr_drbg_context ctx;
Gilles Peskine449bd832023-01-11 14:50:10 +0100952 unsigned char buf[sizeof(result_pr)];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000953
Gilles Peskine449bd832023-01-11 14:50:10 +0100954 mbedtls_ctr_drbg_init(&ctx);
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200955
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000956 /*
957 * Based on a NIST CTR_DRBG test vector (PR = True)
958 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100959 if (verbose != 0) {
960 mbedtls_printf(" CTR_DRBG (PR = TRUE) : ");
961 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000962
963 test_offset = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100964 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)));
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000974
Gilles Peskine449bd832023-01-11 14:50:10 +0100975 mbedtls_ctr_drbg_free(&ctx);
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100976
Gilles Peskine449bd832023-01-11 14:50:10 +0100977 if (verbose != 0) {
978 mbedtls_printf("passed\n");
979 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000980
981 /*
982 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
983 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100984 if (verbose != 0) {
985 mbedtls_printf(" CTR_DRBG (PR = FALSE): ");
986 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000987
Gilles Peskine449bd832023-01-11 14:50:10 +0100988 mbedtls_ctr_drbg_init(&ctx);
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100989
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000990 test_offset = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100991 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)));
Paul Bakker0e04d0e2011-11-27 14:46:59 +00001001
Gilles Peskine449bd832023-01-11 14:50:10 +01001002 mbedtls_ctr_drbg_free(&ctx);
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +01001003
Gilles Peskine449bd832023-01-11 14:50:10 +01001004 if (verbose != 0) {
1005 mbedtls_printf("passed\n");
1006 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +00001007
Gilles Peskine449bd832023-01-11 14:50:10 +01001008 if (verbose != 0) {
1009 mbedtls_printf("\n");
1010 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +00001011
Gilles Peskine449bd832023-01-11 14:50:10 +01001012 return 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +00001013}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001014#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +00001015
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001016#endif /* MBEDTLS_CTR_DRBG_C */