blob: f3995f709c36e31b2efcabf070cc89ec848d6b49 [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
Gilles Peskine449bd832023-01-11 14:50:10 +0100372 for (i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000373 tmp[i] ^= data[i];
Gilles Peskine449bd832023-01-11 14:50:10 +0100374 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000375
376 /*
377 * Update key and counter
378 */
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100379#if defined(MBEDTLS_AES_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100380 if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, tmp,
381 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200382 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300383 }
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100384#else
385 ctr_drbg_destroy_psa_contex(&ctx->psa_ctx);
386
387 status = ctr_drbg_setup_psa_context(&ctx->psa_ctx, tmp, MBEDTLS_CTR_DRBG_KEYSIZE);
388 if (status != PSA_SUCCESS) {
389 ret = psa_generic_status_to_mbedtls(status);
390 goto exit;
391 }
392#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100393 memcpy(ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
394 MBEDTLS_CTR_DRBG_BLOCKSIZE);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000395
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200396exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100397 mbedtls_platform_zeroize(tmp, sizeof(tmp));
398 return ret;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000399}
400
Gilles Peskineed7da592018-08-03 20:16:52 +0200401/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
TRodziewicz26371e42021-06-08 16:45:41 +0200402 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
Gilles Peskineed7da592018-08-03 20:16:52 +0200403 * implements
404 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
405 * security_strength) -> initial_working_state
406 * with inputs
407 * ctx->counter = all-bits-0
408 * ctx->aes_ctx = context from all-bits-0 key
409 * additional[:add_len] = entropy_input || nonce || personalization_string
410 * and with outputs
411 * ctx = initial_working_state
412 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100413int mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context *ctx,
414 const unsigned char *additional,
415 size_t add_len)
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000416{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200417 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Janos Follath24eed8d2019-11-22 13:21:35 +0000418 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000419
Gilles Peskine449bd832023-01-11 14:50:10 +0100420 if (add_len == 0) {
421 return 0;
422 }
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100423
Gilles Peskine449bd832023-01-11 14:50:10 +0100424 if ((ret = block_cipher_df(add_input, additional, add_len)) != 0) {
Gilles Peskined9199932018-09-11 16:41:54 +0200425 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100426 }
427 if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {
Gilles Peskined9199932018-09-11 16:41:54 +0200428 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100429 }
Gilles Peskined9199932018-09-11 16:41:54 +0200430
431exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100432 mbedtls_platform_zeroize(add_input, sizeof(add_input));
433 return ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000434}
435
Gilles Peskineed7da592018-08-03 20:16:52 +0200436/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
Gilles Peskine9be50982019-10-22 18:42:27 +0200437 * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
Gilles Peskineed7da592018-08-03 20:16:52 +0200438 * implements
439 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
440 * -> new_working_state
441 * with inputs
442 * ctx contains working_state
443 * additional[:len] = additional_input
444 * and entropy_input comes from calling ctx->f_entropy
Gilles Peskine9be50982019-10-22 18:42:27 +0200445 * for (ctx->entropy_len + nonce_len) bytes
Gilles Peskineed7da592018-08-03 20:16:52 +0200446 * and with output
447 * ctx contains new_working_state
448 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100449static int mbedtls_ctr_drbg_reseed_internal(mbedtls_ctr_drbg_context *ctx,
450 const unsigned char *additional,
451 size_t len,
452 size_t nonce_len)
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000453{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200454 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000455 size_t seedlen = 0;
Janos Follath24eed8d2019-11-22 13:21:35 +0000456 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000457
Gilles Peskine449bd832023-01-11 14:50:10 +0100458 if (ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
459 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
460 }
461 if (nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len) {
462 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
463 }
464 if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len) {
465 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
466 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000467
Gilles Peskine449bd832023-01-11 14:50:10 +0100468 memset(seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT);
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000469
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200470 /* Gather entropy_len bytes of entropy to seed state. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100471 if (0 != ctx->f_entropy(ctx->p_entropy, seed, ctx->entropy_len)) {
472 return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000473 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000474 seedlen += ctx->entropy_len;
475
Gilles Peskine9be50982019-10-22 18:42:27 +0200476 /* Gather entropy for a nonce if requested. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100477 if (nonce_len != 0) {
478 if (0 != ctx->f_entropy(ctx->p_entropy, seed + seedlen, nonce_len)) {
479 return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
Gilles Peskine9be50982019-10-22 18:42:27 +0200480 }
481 seedlen += nonce_len;
482 }
483
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200484 /* Add additional data if provided. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100485 if (additional != NULL && len != 0) {
486 memcpy(seed + seedlen, additional, len);
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000487 seedlen += len;
488 }
489
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200490 /* Reduce to 384 bits. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100491 if ((ret = block_cipher_df(seed, seed, seedlen)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200492 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100493 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000494
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200495 /* Update state. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100496 if ((ret = ctr_drbg_update_internal(ctx, seed)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200497 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100498 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000499 ctx->reseed_counter = 1;
500
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200501exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100502 mbedtls_platform_zeroize(seed, sizeof(seed));
503 return ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000504}
Paul Bakker9af723c2014-05-01 13:03:14 +0200505
Gilles Peskine449bd832023-01-11 14:50:10 +0100506int mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context *ctx,
507 const unsigned char *additional, size_t len)
Gilles Peskine9be50982019-10-22 18:42:27 +0200508{
Gilles Peskine449bd832023-01-11 14:50:10 +0100509 return mbedtls_ctr_drbg_reseed_internal(ctx, additional, len, 0);
Gilles Peskine9be50982019-10-22 18:42:27 +0200510}
511
Gilles Peskinee9a34542019-10-22 20:43:24 +0200512/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
513 * is sufficient to achieve the maximum security strength given the key
514 * size and entropy length. If there is enough entropy in the initial
515 * call to the entropy function to serve as both the entropy input and
516 * the nonce, don't make a second call to get a nonce. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100517static size_t good_nonce_len(size_t entropy_len)
Gilles Peskinee9a34542019-10-22 20:43:24 +0200518{
Gilles Peskine449bd832023-01-11 14:50:10 +0100519 if (entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2) {
520 return 0;
521 } else {
522 return (entropy_len + 1) / 2;
523 }
Gilles Peskinee9a34542019-10-22 20:43:24 +0200524}
525
Gilles Peskine8bf56132019-10-02 20:31:54 +0200526/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
Gilles Peskine379561f2019-10-18 16:57:48 +0200527 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
Gilles Peskine8bf56132019-10-02 20:31:54 +0200528 * implements
529 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
530 * security_strength) -> initial_working_state
531 * with inputs
532 * custom[:len] = nonce || personalization_string
Gilles Peskine379561f2019-10-18 16:57:48 +0200533 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
Gilles Peskine8bf56132019-10-02 20:31:54 +0200534 * and with outputs
535 * ctx = initial_working_state
536 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100537int mbedtls_ctr_drbg_seed(mbedtls_ctr_drbg_context *ctx,
538 int (*f_entropy)(void *, unsigned char *, size_t),
539 void *p_entropy,
540 const unsigned char *custom,
541 size_t len)
Gilles Peskine8bf56132019-10-02 20:31:54 +0200542{
Janos Follath24eed8d2019-11-22 13:21:35 +0000543 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200544 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Gilles Peskinee9a34542019-10-22 20:43:24 +0200545 size_t nonce_len;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200546
Gilles Peskine449bd832023-01-11 14:50:10 +0100547 memset(key, 0, MBEDTLS_CTR_DRBG_KEYSIZE);
Gilles Peskine8bf56132019-10-02 20:31:54 +0200548
Gilles Peskineda290f92021-02-09 18:44:02 +0100549 /* The mutex is initialized iff f_entropy is set. */
Gilles Peskinef4b34292021-01-30 13:05:32 +0100550#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100551 mbedtls_mutex_init(&ctx->mutex);
Gilles Peskinef4b34292021-01-30 13:05:32 +0100552#endif
553
Gilles Peskine8bf56132019-10-02 20:31:54 +0200554 ctx->f_entropy = f_entropy;
555 ctx->p_entropy = p_entropy;
556
Gilles Peskine449bd832023-01-11 14:50:10 +0100557 if (ctx->entropy_len == 0) {
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200558 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskine449bd832023-01-11 14:50:10 +0100559 }
Gilles Peskinee9a34542019-10-22 20:43:24 +0200560 /* ctx->reseed_counter contains the desired amount of entropy to
561 * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
562 * If it's -1, indicating that the entropy nonce length was not set
563 * explicitly, use a sufficiently large nonce for security. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100564 nonce_len = (ctx->reseed_counter >= 0 ?
565 (size_t) ctx->reseed_counter :
566 good_nonce_len(ctx->entropy_len));
Gilles Peskinee9a34542019-10-22 20:43:24 +0200567
Gilles Peskine9be50982019-10-22 18:42:27 +0200568 /* Initialize with an empty key. */
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100569#if defined(MBEDTLS_AES_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100570 if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, key,
571 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
572 return ret;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200573 }
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100574#else
575 psa_status_t status;
576
577 status = ctr_drbg_setup_psa_context(&ctx->psa_ctx, key, MBEDTLS_CTR_DRBG_KEYSIZE);
578 if (status != PSA_SUCCESS) {
579 ret = psa_generic_status_to_mbedtls(status);
580 return status;
581 }
582#endif
Gilles Peskine8bf56132019-10-02 20:31:54 +0200583
Gilles Peskinee9a34542019-10-22 20:43:24 +0200584 /* Do the initial seeding. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100585 if ((ret = mbedtls_ctr_drbg_reseed_internal(ctx, custom, len,
586 nonce_len)) != 0) {
587 return ret;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200588 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100589 return 0;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200590}
591
Gilles Peskineed7da592018-08-03 20:16:52 +0200592/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
593 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
594 * implements
595 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
596 * -> working_state_after_reseed
597 * if required, then
598 * CTR_DRBG_Generate(working_state_after_reseed,
599 * requested_number_of_bits, additional_input)
600 * -> status, returned_bits, new_working_state
601 * with inputs
602 * ctx contains working_state
603 * requested_number_of_bits = 8 * output_len
604 * additional[:add_len] = additional_input
605 * and entropy_input comes from calling ctx->f_entropy
606 * and with outputs
607 * status = SUCCESS (this function does the reseed internally)
608 * returned_bits = output[:output_len]
609 * ctx contains new_working_state
610 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100611int mbedtls_ctr_drbg_random_with_add(void *p_rng,
612 unsigned char *output, size_t output_len,
613 const unsigned char *additional, size_t add_len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000614{
615 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200616 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
617 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000618 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200619 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000620 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000621 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000622
Gilles Peskine449bd832023-01-11 14:50:10 +0100623 if (output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST) {
624 return MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG;
625 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000626
Gilles Peskine449bd832023-01-11 14:50:10 +0100627 if (add_len > MBEDTLS_CTR_DRBG_MAX_INPUT) {
628 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
629 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000630
Gilles Peskine449bd832023-01-11 14:50:10 +0100631 memset(add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000632
Gilles Peskine449bd832023-01-11 14:50:10 +0100633 if (ctx->reseed_counter > ctx->reseed_interval ||
634 ctx->prediction_resistance) {
635 if ((ret = mbedtls_ctr_drbg_reseed(ctx, additional, add_len)) != 0) {
636 return ret;
Dvir Markovich1b364992017-06-26 13:43:34 +0300637 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000638 add_len = 0;
639 }
640
Gilles Peskine449bd832023-01-11 14:50:10 +0100641 if (add_len > 0) {
642 if ((ret = block_cipher_df(add_input, additional, add_len)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200643 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100644 }
645 if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200646 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100647 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000648 }
649
Gilles Peskine449bd832023-01-11 14:50:10 +0100650 while (output_len > 0) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000651 /*
Dave Rodgman591ff052024-01-13 16:42:38 +0000652 * Increase counter (treat it as a 128-bit big-endian integer).
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000653 */
Dave Rodgman591ff052024-01-13 16:42:38 +0000654 mbedtls_ctr_increment_counter(ctx->counter);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000655
656 /*
657 * Crypt counter block
658 */
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100659#if defined(MBEDTLS_AES_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100660 if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
661 ctx->counter, tmp)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200662 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300663 }
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100664#else
665 psa_status_t status;
666 size_t tmp_len;
667
668 status = psa_cipher_update(&ctx->psa_ctx.operation, ctx->counter, sizeof(ctx->counter),
669 tmp, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);
670 if (status != PSA_SUCCESS) {
671 ret = psa_generic_status_to_mbedtls(status);
672 goto exit;
673 }
674#endif
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000675
Gilles Peskine449bd832023-01-11 14:50:10 +0100676 use_len = (output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE)
Hanno Beckera08651f2018-10-05 09:38:59 +0100677 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000678 /*
679 * Copy random block to destination
680 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100681 memcpy(p, tmp, use_len);
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000682 p += use_len;
683 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000684 }
685
Gilles Peskine449bd832023-01-11 14:50:10 +0100686 if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200687 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100688 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000689
690 ctx->reseed_counter++;
691
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200692exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100693 mbedtls_platform_zeroize(add_input, sizeof(add_input));
694 mbedtls_platform_zeroize(tmp, sizeof(tmp));
695 return ret;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000696}
697
Gilles Peskine449bd832023-01-11 14:50:10 +0100698int mbedtls_ctr_drbg_random(void *p_rng, unsigned char *output,
699 size_t output_len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000700{
Janos Follath24eed8d2019-11-22 13:21:35 +0000701 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100702 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
703
704#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100705 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
706 return ret;
707 }
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100708#endif
709
Gilles Peskine449bd832023-01-11 14:50:10 +0100710 ret = mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, NULL, 0);
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100711
712#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100713 if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
714 return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
715 }
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100716#endif
717
Gilles Peskine449bd832023-01-11 14:50:10 +0100718 return ret;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000719}
720
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200721#if defined(MBEDTLS_FS_IO)
Gilles Peskine449bd832023-01-11 14:50:10 +0100722int mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context *ctx,
723 const char *path)
Paul Bakkerfc754a92011-12-05 13:23:51 +0000724{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200725 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000726 FILE *f;
Gilles Peskine449bd832023-01-11 14:50:10 +0100727 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000728
Gilles Peskine449bd832023-01-11 14:50:10 +0100729 if ((f = fopen(path, "wb")) == NULL) {
730 return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
731 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000732
Gilles Peskineda0913b2022-06-30 17:03:40 +0200733 /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100734 mbedtls_setbuf(f, NULL);
Gilles Peskineda0913b2022-06-30 17:03:40 +0200735
Gilles Peskine449bd832023-01-11 14:50:10 +0100736 if ((ret = mbedtls_ctr_drbg_random(ctx, buf,
737 MBEDTLS_CTR_DRBG_MAX_INPUT)) != 0) {
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200738 goto exit;
Hanno Beckera08651f2018-10-05 09:38:59 +0100739 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100740
741 if (fwrite(buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f) !=
742 MBEDTLS_CTR_DRBG_MAX_INPUT) {
743 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
744 } else {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100745 ret = 0;
Hanno Beckera08651f2018-10-05 09:38:59 +0100746 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000747
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100748exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100749 mbedtls_platform_zeroize(buf, sizeof(buf));
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200750
Gilles Peskine449bd832023-01-11 14:50:10 +0100751 fclose(f);
752 return ret;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000753}
754
Gilles Peskine449bd832023-01-11 14:50:10 +0100755int mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context *ctx,
756 const char *path)
Paul Bakkerfc754a92011-12-05 13:23:51 +0000757{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100758 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200759 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000760 size_t n;
Gilles Peskine449bd832023-01-11 14:50:10 +0100761 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT];
Gilles Peskine82204662018-09-11 18:43:09 +0200762 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000763
Gilles Peskine449bd832023-01-11 14:50:10 +0100764 if ((f = fopen(path, "rb")) == NULL) {
765 return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
766 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000767
Gilles Peskineda0913b2022-06-30 17:03:40 +0200768 /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100769 mbedtls_setbuf(f, NULL);
Gilles Peskineda0913b2022-06-30 17:03:40 +0200770
Gilles Peskine449bd832023-01-11 14:50:10 +0100771 n = fread(buf, 1, sizeof(buf), f);
772 if (fread(&c, 1, 1, f) != 0) {
Gilles Peskine82204662018-09-11 18:43:09 +0200773 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
774 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100775 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100776 if (n == 0 || ferror(f)) {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100777 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200778 goto exit;
779 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100780 fclose(f);
Gilles Peskine82204662018-09-11 18:43:09 +0200781 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200782
Gilles Peskine449bd832023-01-11 14:50:10 +0100783 ret = mbedtls_ctr_drbg_update(ctx, buf, n);
Gilles Peskine82204662018-09-11 18:43:09 +0200784
785exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100786 mbedtls_platform_zeroize(buf, sizeof(buf));
787 if (f != NULL) {
788 fclose(f);
789 }
790 if (ret != 0) {
791 return ret;
792 }
793 return mbedtls_ctr_drbg_write_seed_file(ctx, path);
Paul Bakkerfc754a92011-12-05 13:23:51 +0000794}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200795#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000796
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200797#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000798
ENT\stroej170f63d02020-12-28 08:50:23 -0600799/* The CTR_DRBG NIST test vectors used here are available at
800 * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip
801 *
802 * The parameters used to derive the test data are:
803 *
804 * [AES-128 use df]
805 * [PredictionResistance = True/False]
806 * [EntropyInputLen = 128]
807 * [NonceLen = 64]
808 * [PersonalizationStringLen = 128]
809 * [AdditionalInputLen = 0]
810 * [ReturnedBitsLen = 512]
811 *
812 * [AES-256 use df]
813 * [PredictionResistance = True/False]
814 * [EntropyInputLen = 256]
815 * [NonceLen = 128]
816 * [PersonalizationStringLen = 256]
817 * [AdditionalInputLen = 0]
818 * [ReturnedBitsLen = 512]
819 *
820 */
821
Gilles Peskine02e79a42019-10-07 17:06:06 +0200822#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
ENT\stroej1df307002020-12-26 12:41:04 -0600823static const unsigned char entropy_source_pr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100824{ 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb,
825 0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92,
826 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8,
827 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20,
828 0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0,
829 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad,
830 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200831
ENT\stroej1df307002020-12-26 12:41:04 -0600832static const unsigned char entropy_source_nopr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100833{ 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45,
834 0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9,
835 0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20,
836 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f,
837 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c };
ENT\stroej1df307002020-12-26 12:41:04 -0600838
stroebeljcd4de1b52021-01-04 18:14:32 -0600839static const unsigned char pers_pr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100840{ 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a,
841 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad };
ENT\stroej1df307002020-12-26 12:41:04 -0600842
stroebeljcd4de1b52021-01-04 18:14:32 -0600843static const unsigned char pers_nopr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100844{ 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c,
845 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f };
ENT\stroej1df307002020-12-26 12:41:04 -0600846
847static const unsigned char result_pr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100848{ 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66,
849 0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff,
850 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10,
851 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30,
852 0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4,
853 0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc,
854 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06,
855 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf };
ENT\stroej1df307002020-12-26 12:41:04 -0600856
857static const unsigned char result_nopr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100858{ 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13,
859 0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0,
860 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf,
861 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2,
862 0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7,
863 0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2,
864 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02,
865 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200866#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000867
ENT\stroej1df307002020-12-26 12:41:04 -0600868static const unsigned char entropy_source_pr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100869{ 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49,
870 0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a,
871 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85,
872 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e,
873 0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15,
874 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45,
875 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8,
876 0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c,
877 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3,
878 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce,
879 0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e,
880 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76,
881 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77,
882 0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe };
ENT\stroej1df307002020-12-26 12:41:04 -0600883
884static const unsigned char entropy_source_nopr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100885{ 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d,
886 0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0,
887 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73,
888 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c,
889 0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2,
890 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1,
891 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a,
892 0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb,
893 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a,
894 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 };
ENT\stroej1df307002020-12-26 12:41:04 -0600895
stroebeljcd4de1b52021-01-04 18:14:32 -0600896static const unsigned char pers_pr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100897{ 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33,
898 0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e,
899 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0,
900 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 };
ENT\stroej1df307002020-12-26 12:41:04 -0600901
stroebeljcd4de1b52021-01-04 18:14:32 -0600902static const unsigned char pers_nopr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100903{ 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29,
904 0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf,
905 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb,
906 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b };
ENT\stroej1df307002020-12-26 12:41:04 -0600907
908static const unsigned char result_pr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100909{ 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85,
910 0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d,
911 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62,
912 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d,
913 0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb,
914 0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39,
915 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40,
916 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 };
ENT\stroej1df307002020-12-26 12:41:04 -0600917
918static const unsigned char result_nopr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100919{ 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad,
920 0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3,
921 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b,
922 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14,
923 0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54,
924 0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30,
925 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a,
926 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200927#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000928
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100929static size_t test_offset;
Gilles Peskine449bd832023-01-11 14:50:10 +0100930static int ctr_drbg_self_test_entropy(void *data, unsigned char *buf,
931 size_t len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000932{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100933 const unsigned char *p = data;
Gilles Peskine449bd832023-01-11 14:50:10 +0100934 memcpy(buf, p + test_offset, len);
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100935 test_offset += len;
Gilles Peskine449bd832023-01-11 14:50:10 +0100936 return 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000937}
938
Gilles Peskine449bd832023-01-11 14:50:10 +0100939#define CHK(c) if ((c) != 0) \
940 { \
941 if (verbose != 0) \
942 mbedtls_printf("failed\n"); \
943 return 1; \
944 }
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100945
bootstrap-prime6dbbf442022-05-17 19:30:44 -0400946#define SELF_TEST_OUTPUT_DISCARD_LENGTH 64
stroebeljcd4de1b52021-01-04 18:14:32 -0600947
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000948/*
949 * Checkup routine
950 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100951int mbedtls_ctr_drbg_self_test(int verbose)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000952{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200953 mbedtls_ctr_drbg_context ctx;
Gilles Peskine449bd832023-01-11 14:50:10 +0100954 unsigned char buf[sizeof(result_pr)];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000955
Gilles Peskine449bd832023-01-11 14:50:10 +0100956 mbedtls_ctr_drbg_init(&ctx);
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200957
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000958 /*
959 * Based on a NIST CTR_DRBG test vector (PR = True)
960 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100961 if (verbose != 0) {
962 mbedtls_printf(" CTR_DRBG (PR = TRUE) : ");
963 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000964
965 test_offset = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100966 mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
967 mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2);
968 CHK(mbedtls_ctr_drbg_seed(&ctx,
969 ctr_drbg_self_test_entropy,
970 (void *) entropy_source_pr,
971 pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE));
972 mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_ON);
973 CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH));
974 CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_pr)));
975 CHK(memcmp(buf, result_pr, sizeof(result_pr)));
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000976
Gilles Peskine449bd832023-01-11 14:50:10 +0100977 mbedtls_ctr_drbg_free(&ctx);
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100978
Gilles Peskine449bd832023-01-11 14:50:10 +0100979 if (verbose != 0) {
980 mbedtls_printf("passed\n");
981 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000982
983 /*
984 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
985 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100986 if (verbose != 0) {
987 mbedtls_printf(" CTR_DRBG (PR = FALSE): ");
988 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000989
Gilles Peskine449bd832023-01-11 14:50:10 +0100990 mbedtls_ctr_drbg_init(&ctx);
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100991
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000992 test_offset = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100993 mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
994 mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2);
995 CHK(mbedtls_ctr_drbg_seed(&ctx,
996 ctr_drbg_self_test_entropy,
997 (void *) entropy_source_nopr,
998 pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE));
999 CHK(mbedtls_ctr_drbg_reseed(&ctx, NULL, 0));
1000 CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH));
1001 CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_nopr)));
1002 CHK(memcmp(buf, result_nopr, sizeof(result_nopr)));
Paul Bakker0e04d0e2011-11-27 14:46:59 +00001003
Gilles Peskine449bd832023-01-11 14:50:10 +01001004 mbedtls_ctr_drbg_free(&ctx);
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +01001005
Gilles Peskine449bd832023-01-11 14:50:10 +01001006 if (verbose != 0) {
1007 mbedtls_printf("passed\n");
1008 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +00001009
Gilles Peskine449bd832023-01-11 14:50:10 +01001010 if (verbose != 0) {
1011 mbedtls_printf("\n");
1012 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +00001013
Gilles Peskine449bd832023-01-11 14:50:10 +01001014 return 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +00001015}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001016#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +00001017
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001018#endif /* MBEDTLS_CTR_DRBG_C */