blob: da34f950b8cd53df368efbe0af186622818c2acf [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
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000017#include "mbedtls/ctr_drbg.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050018#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000019#include "mbedtls/error.h"
Paul Bakker0e04d0e2011-11-27 14:46:59 +000020
Rich Evans00ab4702015-02-06 13:43:58 +000021#include <string.h>
22
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020023#if defined(MBEDTLS_FS_IO)
Paul Bakkerfc754a92011-12-05 13:23:51 +000024#include <stdio.h>
25#endif
26
Valerio Setti5f4b28d2023-11-13 10:18:16 +010027/* Using error translation functions from PSA to MbedTLS */
28#if !defined(MBEDTLS_AES_C)
29#include "psa_util_internal.h"
30#endif
31
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000032#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010033
Valerio Setti5f4b28d2023-11-13 10:18:16 +010034#if !defined(MBEDTLS_AES_C)
35static psa_status_t ctr_drbg_setup_psa_context(mbedtls_ctr_drbg_psa_context *psa_ctx,
36 unsigned char *key, size_t key_len)
37{
38 psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
39 psa_status_t status;
40
41 psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT);
42 psa_set_key_algorithm(&key_attr, PSA_ALG_ECB_NO_PADDING);
43 psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
44 status = psa_import_key(&key_attr, key, key_len, &psa_ctx->key_id);
45 if (status != PSA_SUCCESS) {
46 goto exit;
47 }
48
49 status = psa_cipher_encrypt_setup(&psa_ctx->operation, psa_ctx->key_id, PSA_ALG_ECB_NO_PADDING);
50 if (status != PSA_SUCCESS) {
51 goto exit;
52 }
53
54exit:
55 psa_reset_key_attributes(&key_attr);
56 return status;
57}
58
59static void ctr_drbg_destroy_psa_contex(mbedtls_ctr_drbg_psa_context *psa_ctx)
60{
61 psa_cipher_abort(&psa_ctx->operation);
62 psa_destroy_key(psa_ctx->key_id);
63
64 psa_ctx->operation = psa_cipher_operation_init();
65 psa_ctx->key_id = MBEDTLS_SVC_KEY_ID_INIT;
66}
67#endif
68
Paul Bakker18d32912011-12-10 21:42:49 +000069/*
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020070 * CTR_DRBG context initialization
71 */
Gilles Peskine449bd832023-01-11 14:50:10 +010072void mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context *ctx)
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020073{
Gilles Peskine449bd832023-01-11 14:50:10 +010074 memset(ctx, 0, sizeof(mbedtls_ctr_drbg_context));
Valerio Setti5f4b28d2023-11-13 10:18:16 +010075#if defined(MBEDTLS_AES_C)
Gilles Peskine449bd832023-01-11 14:50:10 +010076 mbedtls_aes_init(&ctx->aes_ctx);
Valerio Setti5f4b28d2023-11-13 10:18:16 +010077#else
78 ctx->psa_ctx.key_id = MBEDTLS_SVC_KEY_ID_INIT;
79 ctx->psa_ctx.operation = psa_cipher_operation_init();
80#endif
Gilles Peskinee9a34542019-10-22 20:43:24 +020081 /* Indicate that the entropy nonce length is not set explicitly.
82 * See mbedtls_ctr_drbg_set_nonce_len(). */
83 ctx->reseed_counter = -1;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010084
Gavin Acquroff6aceb512020-03-01 17:06:11 -080085 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020086}
87
Gavin Acquroff6aceb512020-03-01 17:06:11 -080088/*
89 * This function resets CTR_DRBG context to the state immediately
90 * after initial call of mbedtls_ctr_drbg_init().
91 */
Gilles Peskine449bd832023-01-11 14:50:10 +010092void mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context *ctx)
Paul Bakkerfff03662014-06-18 16:21:25 +020093{
Gilles Peskine449bd832023-01-11 14:50:10 +010094 if (ctx == NULL) {
Paul Bakkerfff03662014-06-18 16:21:25 +020095 return;
Gilles Peskine449bd832023-01-11 14:50:10 +010096 }
Paul Bakkerfff03662014-06-18 16:21:25 +020097
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010098#if defined(MBEDTLS_THREADING_C)
Gilles Peskineda290f92021-02-09 18:44:02 +010099 /* The mutex is initialized iff f_entropy is set. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100100 if (ctx->f_entropy != NULL) {
101 mbedtls_mutex_free(&ctx->mutex);
102 }
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100103#endif
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100104#if defined(MBEDTLS_AES_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100105 mbedtls_aes_free(&ctx->aes_ctx);
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100106#else
107 ctr_drbg_destroy_psa_contex(&ctx->psa_ctx);
108#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100109 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ctr_drbg_context));
Gavin Acquroff6aceb512020-03-01 17:06:11 -0800110 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
111 ctx->reseed_counter = -1;
Paul Bakkerfff03662014-06-18 16:21:25 +0200112}
113
Gilles Peskine449bd832023-01-11 14:50:10 +0100114void mbedtls_ctr_drbg_set_prediction_resistance(mbedtls_ctr_drbg_context *ctx,
115 int resistance)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000116{
117 ctx->prediction_resistance = resistance;
118}
119
Gilles Peskine449bd832023-01-11 14:50:10 +0100120void mbedtls_ctr_drbg_set_entropy_len(mbedtls_ctr_drbg_context *ctx,
121 size_t len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000122{
123 ctx->entropy_len = len;
124}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200125
Gilles Peskine449bd832023-01-11 14:50:10 +0100126int mbedtls_ctr_drbg_set_nonce_len(mbedtls_ctr_drbg_context *ctx,
127 size_t len)
Gilles Peskine9be50982019-10-22 18:42:27 +0200128{
129 /* If mbedtls_ctr_drbg_seed() has already been called, it's
130 * too late. Return the error code that's closest to making sense. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100131 if (ctx->f_entropy != NULL) {
132 return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
133 }
Gilles Peskine9be50982019-10-22 18:42:27 +0200134
Gilles Peskine449bd832023-01-11 14:50:10 +0100135 if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
136 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
137 }
Dave Rodgman4a5c9ee2023-02-10 16:03:44 +0000138
Gilles Peskine9be50982019-10-22 18:42:27 +0200139 /* This shouldn't be an issue because
140 * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible
141 * configuration, but make sure anyway. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100142 if (len > INT_MAX) {
143 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
144 }
Gilles Peskine9be50982019-10-22 18:42:27 +0200145
146 /* For backward compatibility with Mbed TLS <= 2.19, store the
147 * entropy nonce length in a field that already exists, but isn't
148 * used until after the initial seeding. */
149 /* Due to the capping of len above, the value fits in an int. */
150 ctx->reseed_counter = (int) len;
Gilles Peskine449bd832023-01-11 14:50:10 +0100151 return 0;
Gilles Peskine9be50982019-10-22 18:42:27 +0200152}
153
Gilles Peskine449bd832023-01-11 14:50:10 +0100154void mbedtls_ctr_drbg_set_reseed_interval(mbedtls_ctr_drbg_context *ctx,
155 int interval)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000156{
157 ctx->reseed_interval = interval;
158}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200159
Gilles Peskine449bd832023-01-11 14:50:10 +0100160static int block_cipher_df(unsigned char *output,
161 const unsigned char *data, size_t data_len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000162{
Hanno Beckera08651f2018-10-05 09:38:59 +0100163 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
164 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200165 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
166 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
167 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100168 unsigned char *p, *iv;
Dvir Markovich1b364992017-06-26 13:43:34 +0300169 int ret = 0;
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100170#if defined(MBEDTLS_AES_C)
171 mbedtls_aes_context aes_ctx;
172#else
173 psa_status_t status;
174 size_t tmp_len;
175 mbedtls_ctr_drbg_psa_context psa_ctx;
176
177 psa_ctx.key_id = MBEDTLS_SVC_KEY_ID_INIT;
178 psa_ctx.operation = psa_cipher_operation_init();
179#endif
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000180
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200181 int i, j;
182 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000183
Gilles Peskine449bd832023-01-11 14:50:10 +0100184 if (data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
185 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
186 }
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100187
Gilles Peskine449bd832023-01-11 14:50:10 +0100188 memset(buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
189 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000190
191 /*
192 * Construct IV (16 bytes) and S in buffer
193 * IV = Counter (in 32-bits) padded to 16 with zeroes
194 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
195 * data || 0x80
196 * (Total is padded to a multiple of 16-bytes with zeroes)
197 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200198 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Gilles Peskine449bd832023-01-11 14:50:10 +0100199 MBEDTLS_PUT_UINT32_BE(data_len, p, 0);
Joe Subbiania5cb0d22021-08-23 11:35:25 +0100200 p += 4 + 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200201 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Gilles Peskine449bd832023-01-11 14:50:10 +0100202 memcpy(p, data, data_len);
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000203 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000204
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200205 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000206
Gilles Peskine449bd832023-01-11 14:50:10 +0100207 for (i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000208 key[i] = i;
Gilles Peskine449bd832023-01-11 14:50:10 +0100209 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000210
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100211#if defined(MBEDTLS_AES_C)
212 mbedtls_aes_init(&aes_ctx);
213
Gilles Peskine449bd832023-01-11 14:50:10 +0100214 if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, key,
215 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300216 goto exit;
217 }
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100218#else
219 status = ctr_drbg_setup_psa_context(&psa_ctx, key, sizeof(key));
220 if (status != PSA_SUCCESS) {
221 ret = psa_generic_status_to_mbedtls(status);
222 goto exit;
223 }
224#endif
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000225
226 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200227 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000228 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100229 for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000230 p = buf;
Gilles Peskine449bd832023-01-11 14:50:10 +0100231 memset(chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000232 use_len = buf_len;
233
Gilles Peskine449bd832023-01-11 14:50:10 +0100234 while (use_len > 0) {
235 mbedtls_xor(chain, chain, p, MBEDTLS_CTR_DRBG_BLOCKSIZE);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200236 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Gilles Peskine449bd832023-01-11 14:50:10 +0100237 use_len -= (use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE) ?
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200238 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000239
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100240#if defined(MBEDTLS_AES_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100241 if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,
242 chain, chain)) != 0) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300243 goto exit;
244 }
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100245#else
246 status = psa_cipher_update(&psa_ctx.operation, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE,
247 chain, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);
248 if (status != PSA_SUCCESS) {
249 ret = psa_generic_status_to_mbedtls(status);
250 goto exit;
251 }
252#endif
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000253 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200254
Gilles Peskine449bd832023-01-11 14:50:10 +0100255 memcpy(tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000256
257 /*
258 * Update IV
259 */
260 buf[3]++;
261 }
262
263 /*
264 * Do final encryption with reduced data
265 */
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100266#if defined(MBEDTLS_AES_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100267 if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, tmp,
268 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300269 goto exit;
270 }
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100271#else
272 ctr_drbg_destroy_psa_contex(&psa_ctx);
273
274 status = ctr_drbg_setup_psa_context(&psa_ctx, tmp, MBEDTLS_CTR_DRBG_KEYSIZE);
275 if (status != PSA_SUCCESS) {
276 ret = psa_generic_status_to_mbedtls(status);
277 goto exit;
278 }
279#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200280 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000281 p = output;
282
Gilles Peskine449bd832023-01-11 14:50:10 +0100283 for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100284#if defined(MBEDTLS_AES_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100285 if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,
286 iv, iv)) != 0) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300287 goto exit;
288 }
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100289#else
290 status = psa_cipher_update(&psa_ctx.operation, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE,
291 iv, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);
292 if (status != PSA_SUCCESS) {
293 ret = psa_generic_status_to_mbedtls(status);
294 goto exit;
295 }
296#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100297 memcpy(p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200298 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000299 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300300exit:
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100301#if defined(MBEDTLS_AES_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100302 mbedtls_aes_free(&aes_ctx);
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100303#else
304 ctr_drbg_destroy_psa_contex(&psa_ctx);
305#endif
Dvir Markovich1b364992017-06-26 13:43:34 +0300306 /*
Gilles Peskine449bd832023-01-11 14:50:10 +0100307 * tidy up the stack
308 */
309 mbedtls_platform_zeroize(buf, sizeof(buf));
310 mbedtls_platform_zeroize(tmp, sizeof(tmp));
311 mbedtls_platform_zeroize(key, sizeof(key));
312 mbedtls_platform_zeroize(chain, sizeof(chain));
313 if (0 != ret) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300314 /*
Gilles Peskine449bd832023-01-11 14:50:10 +0100315 * wipe partial seed from memory
316 */
317 mbedtls_platform_zeroize(output, MBEDTLS_CTR_DRBG_SEEDLEN);
Dvir Markovich1b364992017-06-26 13:43:34 +0300318 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200319
Gilles Peskine449bd832023-01-11 14:50:10 +0100320 return ret;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000321}
322
Gilles Peskineed7da592018-08-03 20:16:52 +0200323/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
324 * ctr_drbg_update_internal(ctx, provided_data)
325 * implements
326 * CTR_DRBG_Update(provided_data, Key, V)
327 * with inputs and outputs
328 * ctx->aes_ctx = Key
329 * ctx->counter = V
330 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100331static int ctr_drbg_update_internal(mbedtls_ctr_drbg_context *ctx,
332 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN])
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000333{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200334 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000335 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000336 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300337 int ret = 0;
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100338#if !defined(MBEDTLS_AES_C)
339 psa_status_t status;
340 size_t tmp_len;
341#endif
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000342
Gilles Peskine449bd832023-01-11 14:50:10 +0100343 memset(tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000344
Gilles Peskine449bd832023-01-11 14:50:10 +0100345 for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000346 /*
347 * Increase counter
348 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100349 for (i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i--) {
350 if (++ctx->counter[i - 1] != 0) {
Paul Bakker369e14b2012-04-18 14:16:09 +0000351 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100352 }
353 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000354
355 /*
356 * Crypt counter block
357 */
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100358#if defined(MBEDTLS_AES_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100359 if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
360 ctx->counter, p)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200361 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300362 }
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100363#else
364 status = psa_cipher_update(&ctx->psa_ctx.operation, ctx->counter, sizeof(ctx->counter),
365 p, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);
366 if (status != PSA_SUCCESS) {
367 ret = psa_generic_status_to_mbedtls(status);
368 goto exit;
369 }
370#endif
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000371
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200372 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000373 }
374
Gilles Peskine449bd832023-01-11 14:50:10 +0100375 for (i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000376 tmp[i] ^= data[i];
Gilles Peskine449bd832023-01-11 14:50:10 +0100377 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000378
379 /*
380 * Update key and counter
381 */
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100382#if defined(MBEDTLS_AES_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100383 if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, tmp,
384 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200385 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300386 }
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100387#else
388 ctr_drbg_destroy_psa_contex(&ctx->psa_ctx);
389
390 status = ctr_drbg_setup_psa_context(&ctx->psa_ctx, tmp, MBEDTLS_CTR_DRBG_KEYSIZE);
391 if (status != PSA_SUCCESS) {
392 ret = psa_generic_status_to_mbedtls(status);
393 goto exit;
394 }
395#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100396 memcpy(ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
397 MBEDTLS_CTR_DRBG_BLOCKSIZE);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000398
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200399exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100400 mbedtls_platform_zeroize(tmp, sizeof(tmp));
401 return ret;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000402}
403
Gilles Peskineed7da592018-08-03 20:16:52 +0200404/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
TRodziewicz26371e42021-06-08 16:45:41 +0200405 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
Gilles Peskineed7da592018-08-03 20:16:52 +0200406 * implements
407 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
408 * security_strength) -> initial_working_state
409 * with inputs
410 * ctx->counter = all-bits-0
411 * ctx->aes_ctx = context from all-bits-0 key
412 * additional[:add_len] = entropy_input || nonce || personalization_string
413 * and with outputs
414 * ctx = initial_working_state
415 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100416int mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context *ctx,
417 const unsigned char *additional,
418 size_t add_len)
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000419{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200420 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Janos Follath24eed8d2019-11-22 13:21:35 +0000421 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000422
Gilles Peskine449bd832023-01-11 14:50:10 +0100423 if (add_len == 0) {
424 return 0;
425 }
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100426
Gilles Peskine449bd832023-01-11 14:50:10 +0100427 if ((ret = block_cipher_df(add_input, additional, add_len)) != 0) {
Gilles Peskined9199932018-09-11 16:41:54 +0200428 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100429 }
430 if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {
Gilles Peskined9199932018-09-11 16:41:54 +0200431 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100432 }
Gilles Peskined9199932018-09-11 16:41:54 +0200433
434exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100435 mbedtls_platform_zeroize(add_input, sizeof(add_input));
436 return ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000437}
438
Gilles Peskineed7da592018-08-03 20:16:52 +0200439/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
Gilles Peskine9be50982019-10-22 18:42:27 +0200440 * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
Gilles Peskineed7da592018-08-03 20:16:52 +0200441 * implements
442 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
443 * -> new_working_state
444 * with inputs
445 * ctx contains working_state
446 * additional[:len] = additional_input
447 * and entropy_input comes from calling ctx->f_entropy
Gilles Peskine9be50982019-10-22 18:42:27 +0200448 * for (ctx->entropy_len + nonce_len) bytes
Gilles Peskineed7da592018-08-03 20:16:52 +0200449 * and with output
450 * ctx contains new_working_state
451 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100452static int mbedtls_ctr_drbg_reseed_internal(mbedtls_ctr_drbg_context *ctx,
453 const unsigned char *additional,
454 size_t len,
455 size_t nonce_len)
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000456{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200457 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000458 size_t seedlen = 0;
Janos Follath24eed8d2019-11-22 13:21:35 +0000459 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000460
Gilles Peskine449bd832023-01-11 14:50:10 +0100461 if (ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
462 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
463 }
464 if (nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len) {
465 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
466 }
467 if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len) {
468 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
469 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000470
Gilles Peskine449bd832023-01-11 14:50:10 +0100471 memset(seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT);
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000472
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200473 /* Gather entropy_len bytes of entropy to seed state. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100474 if (0 != ctx->f_entropy(ctx->p_entropy, seed, ctx->entropy_len)) {
475 return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000476 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000477 seedlen += ctx->entropy_len;
478
Gilles Peskine9be50982019-10-22 18:42:27 +0200479 /* Gather entropy for a nonce if requested. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100480 if (nonce_len != 0) {
481 if (0 != ctx->f_entropy(ctx->p_entropy, seed + seedlen, nonce_len)) {
482 return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
Gilles Peskine9be50982019-10-22 18:42:27 +0200483 }
484 seedlen += nonce_len;
485 }
486
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200487 /* Add additional data if provided. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100488 if (additional != NULL && len != 0) {
489 memcpy(seed + seedlen, additional, len);
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000490 seedlen += len;
491 }
492
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200493 /* Reduce to 384 bits. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100494 if ((ret = block_cipher_df(seed, seed, seedlen)) != 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
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200498 /* Update state. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100499 if ((ret = ctr_drbg_update_internal(ctx, seed)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200500 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100501 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000502 ctx->reseed_counter = 1;
503
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200504exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100505 mbedtls_platform_zeroize(seed, sizeof(seed));
506 return ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000507}
Paul Bakker9af723c2014-05-01 13:03:14 +0200508
Gilles Peskine449bd832023-01-11 14:50:10 +0100509int mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context *ctx,
510 const unsigned char *additional, size_t len)
Gilles Peskine9be50982019-10-22 18:42:27 +0200511{
Gilles Peskine449bd832023-01-11 14:50:10 +0100512 return mbedtls_ctr_drbg_reseed_internal(ctx, additional, len, 0);
Gilles Peskine9be50982019-10-22 18:42:27 +0200513}
514
Gilles Peskinee9a34542019-10-22 20:43:24 +0200515/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
516 * is sufficient to achieve the maximum security strength given the key
517 * size and entropy length. If there is enough entropy in the initial
518 * call to the entropy function to serve as both the entropy input and
519 * the nonce, don't make a second call to get a nonce. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100520static size_t good_nonce_len(size_t entropy_len)
Gilles Peskinee9a34542019-10-22 20:43:24 +0200521{
Gilles Peskine449bd832023-01-11 14:50:10 +0100522 if (entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2) {
523 return 0;
524 } else {
525 return (entropy_len + 1) / 2;
526 }
Gilles Peskinee9a34542019-10-22 20:43:24 +0200527}
528
Gilles Peskine8bf56132019-10-02 20:31:54 +0200529/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
Gilles Peskine379561f2019-10-18 16:57:48 +0200530 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
Gilles Peskine8bf56132019-10-02 20:31:54 +0200531 * implements
532 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
533 * security_strength) -> initial_working_state
534 * with inputs
535 * custom[:len] = nonce || personalization_string
Gilles Peskine379561f2019-10-18 16:57:48 +0200536 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
Gilles Peskine8bf56132019-10-02 20:31:54 +0200537 * and with outputs
538 * ctx = initial_working_state
539 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100540int mbedtls_ctr_drbg_seed(mbedtls_ctr_drbg_context *ctx,
541 int (*f_entropy)(void *, unsigned char *, size_t),
542 void *p_entropy,
543 const unsigned char *custom,
544 size_t len)
Gilles Peskine8bf56132019-10-02 20:31:54 +0200545{
Janos Follath24eed8d2019-11-22 13:21:35 +0000546 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200547 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Gilles Peskinee9a34542019-10-22 20:43:24 +0200548 size_t nonce_len;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200549
Gilles Peskine449bd832023-01-11 14:50:10 +0100550 memset(key, 0, MBEDTLS_CTR_DRBG_KEYSIZE);
Gilles Peskine8bf56132019-10-02 20:31:54 +0200551
Gilles Peskineda290f92021-02-09 18:44:02 +0100552 /* The mutex is initialized iff f_entropy is set. */
Gilles Peskinef4b34292021-01-30 13:05:32 +0100553#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100554 mbedtls_mutex_init(&ctx->mutex);
Gilles Peskinef4b34292021-01-30 13:05:32 +0100555#endif
556
Gilles Peskine8bf56132019-10-02 20:31:54 +0200557 ctx->f_entropy = f_entropy;
558 ctx->p_entropy = p_entropy;
559
Gilles Peskine449bd832023-01-11 14:50:10 +0100560 if (ctx->entropy_len == 0) {
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200561 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskine449bd832023-01-11 14:50:10 +0100562 }
Gilles Peskinee9a34542019-10-22 20:43:24 +0200563 /* ctx->reseed_counter contains the desired amount of entropy to
564 * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
565 * If it's -1, indicating that the entropy nonce length was not set
566 * explicitly, use a sufficiently large nonce for security. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100567 nonce_len = (ctx->reseed_counter >= 0 ?
568 (size_t) ctx->reseed_counter :
569 good_nonce_len(ctx->entropy_len));
Gilles Peskinee9a34542019-10-22 20:43:24 +0200570
Gilles Peskine9be50982019-10-22 18:42:27 +0200571 /* Initialize with an empty key. */
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100572#if defined(MBEDTLS_AES_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100573 if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, key,
574 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
575 return ret;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200576 }
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100577#else
578 psa_status_t status;
579
580 status = ctr_drbg_setup_psa_context(&ctx->psa_ctx, key, MBEDTLS_CTR_DRBG_KEYSIZE);
581 if (status != PSA_SUCCESS) {
582 ret = psa_generic_status_to_mbedtls(status);
583 return status;
584 }
585#endif
Gilles Peskine8bf56132019-10-02 20:31:54 +0200586
Gilles Peskinee9a34542019-10-22 20:43:24 +0200587 /* Do the initial seeding. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100588 if ((ret = mbedtls_ctr_drbg_reseed_internal(ctx, custom, len,
589 nonce_len)) != 0) {
590 return ret;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200591 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100592 return 0;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200593}
594
Gilles Peskineed7da592018-08-03 20:16:52 +0200595/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
596 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
597 * implements
598 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
599 * -> working_state_after_reseed
600 * if required, then
601 * CTR_DRBG_Generate(working_state_after_reseed,
602 * requested_number_of_bits, additional_input)
603 * -> status, returned_bits, new_working_state
604 * with inputs
605 * ctx contains working_state
606 * requested_number_of_bits = 8 * output_len
607 * additional[:add_len] = additional_input
608 * and entropy_input comes from calling ctx->f_entropy
609 * and with outputs
610 * status = SUCCESS (this function does the reseed internally)
611 * returned_bits = output[:output_len]
612 * ctx contains new_working_state
613 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100614int mbedtls_ctr_drbg_random_with_add(void *p_rng,
615 unsigned char *output, size_t output_len,
616 const unsigned char *additional, size_t add_len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000617{
618 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200619 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
620 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000621 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200622 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000623 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000624 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000625
Gilles Peskine449bd832023-01-11 14:50:10 +0100626 if (output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST) {
627 return MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG;
628 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000629
Gilles Peskine449bd832023-01-11 14:50:10 +0100630 if (add_len > MBEDTLS_CTR_DRBG_MAX_INPUT) {
631 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
632 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000633
Gilles Peskine449bd832023-01-11 14:50:10 +0100634 memset(add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000635
Gilles Peskine449bd832023-01-11 14:50:10 +0100636 if (ctx->reseed_counter > ctx->reseed_interval ||
637 ctx->prediction_resistance) {
638 if ((ret = mbedtls_ctr_drbg_reseed(ctx, additional, add_len)) != 0) {
639 return ret;
Dvir Markovich1b364992017-06-26 13:43:34 +0300640 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000641 add_len = 0;
642 }
643
Gilles Peskine449bd832023-01-11 14:50:10 +0100644 if (add_len > 0) {
645 if ((ret = block_cipher_df(add_input, additional, add_len)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200646 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100647 }
648 if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200649 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100650 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000651 }
652
Gilles Peskine449bd832023-01-11 14:50:10 +0100653 while (output_len > 0) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000654 /*
655 * Increase counter
656 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100657 for (i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i--) {
658 if (++ctx->counter[i - 1] != 0) {
Paul Bakker369e14b2012-04-18 14:16:09 +0000659 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100660 }
661 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000662
663 /*
664 * Crypt counter block
665 */
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100666#if defined(MBEDTLS_AES_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100667 if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
668 ctx->counter, tmp)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200669 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300670 }
Valerio Setti5f4b28d2023-11-13 10:18:16 +0100671#else
672 psa_status_t status;
673 size_t tmp_len;
674
675 status = psa_cipher_update(&ctx->psa_ctx.operation, ctx->counter, sizeof(ctx->counter),
676 tmp, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);
677 if (status != PSA_SUCCESS) {
678 ret = psa_generic_status_to_mbedtls(status);
679 goto exit;
680 }
681#endif
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000682
Gilles Peskine449bd832023-01-11 14:50:10 +0100683 use_len = (output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE)
Hanno Beckera08651f2018-10-05 09:38:59 +0100684 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000685 /*
686 * Copy random block to destination
687 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100688 memcpy(p, tmp, use_len);
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000689 p += use_len;
690 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000691 }
692
Gilles Peskine449bd832023-01-11 14:50:10 +0100693 if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200694 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100695 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000696
697 ctx->reseed_counter++;
698
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200699exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100700 mbedtls_platform_zeroize(add_input, sizeof(add_input));
701 mbedtls_platform_zeroize(tmp, sizeof(tmp));
702 return ret;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000703}
704
Gilles Peskine449bd832023-01-11 14:50:10 +0100705int mbedtls_ctr_drbg_random(void *p_rng, unsigned char *output,
706 size_t output_len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000707{
Janos Follath24eed8d2019-11-22 13:21:35 +0000708 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100709 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
710
711#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100712 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
713 return ret;
714 }
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100715#endif
716
Gilles Peskine449bd832023-01-11 14:50:10 +0100717 ret = mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, NULL, 0);
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100718
719#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100720 if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
721 return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
722 }
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100723#endif
724
Gilles Peskine449bd832023-01-11 14:50:10 +0100725 return ret;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000726}
727
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200728#if defined(MBEDTLS_FS_IO)
Gilles Peskine449bd832023-01-11 14:50:10 +0100729int mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context *ctx,
730 const char *path)
Paul Bakkerfc754a92011-12-05 13:23:51 +0000731{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200732 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000733 FILE *f;
Gilles Peskine449bd832023-01-11 14:50:10 +0100734 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000735
Gilles Peskine449bd832023-01-11 14:50:10 +0100736 if ((f = fopen(path, "wb")) == NULL) {
737 return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
738 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000739
Gilles Peskineda0913b2022-06-30 17:03:40 +0200740 /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100741 mbedtls_setbuf(f, NULL);
Gilles Peskineda0913b2022-06-30 17:03:40 +0200742
Gilles Peskine449bd832023-01-11 14:50:10 +0100743 if ((ret = mbedtls_ctr_drbg_random(ctx, buf,
744 MBEDTLS_CTR_DRBG_MAX_INPUT)) != 0) {
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200745 goto exit;
Hanno Beckera08651f2018-10-05 09:38:59 +0100746 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100747
748 if (fwrite(buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f) !=
749 MBEDTLS_CTR_DRBG_MAX_INPUT) {
750 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
751 } else {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100752 ret = 0;
Hanno Beckera08651f2018-10-05 09:38:59 +0100753 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000754
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100755exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100756 mbedtls_platform_zeroize(buf, sizeof(buf));
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200757
Gilles Peskine449bd832023-01-11 14:50:10 +0100758 fclose(f);
759 return ret;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000760}
761
Gilles Peskine449bd832023-01-11 14:50:10 +0100762int mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context *ctx,
763 const char *path)
Paul Bakkerfc754a92011-12-05 13:23:51 +0000764{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100765 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200766 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000767 size_t n;
Gilles Peskine449bd832023-01-11 14:50:10 +0100768 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT];
Gilles Peskine82204662018-09-11 18:43:09 +0200769 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000770
Gilles Peskine449bd832023-01-11 14:50:10 +0100771 if ((f = fopen(path, "rb")) == NULL) {
772 return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
773 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000774
Gilles Peskineda0913b2022-06-30 17:03:40 +0200775 /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100776 mbedtls_setbuf(f, NULL);
Gilles Peskineda0913b2022-06-30 17:03:40 +0200777
Gilles Peskine449bd832023-01-11 14:50:10 +0100778 n = fread(buf, 1, sizeof(buf), f);
779 if (fread(&c, 1, 1, f) != 0) {
Gilles Peskine82204662018-09-11 18:43:09 +0200780 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
781 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100782 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100783 if (n == 0 || ferror(f)) {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100784 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200785 goto exit;
786 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100787 fclose(f);
Gilles Peskine82204662018-09-11 18:43:09 +0200788 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200789
Gilles Peskine449bd832023-01-11 14:50:10 +0100790 ret = mbedtls_ctr_drbg_update(ctx, buf, n);
Gilles Peskine82204662018-09-11 18:43:09 +0200791
792exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100793 mbedtls_platform_zeroize(buf, sizeof(buf));
794 if (f != NULL) {
795 fclose(f);
796 }
797 if (ret != 0) {
798 return ret;
799 }
800 return mbedtls_ctr_drbg_write_seed_file(ctx, path);
Paul Bakkerfc754a92011-12-05 13:23:51 +0000801}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200802#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000803
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200804#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000805
ENT\stroej170f63d02020-12-28 08:50:23 -0600806/* The CTR_DRBG NIST test vectors used here are available at
807 * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip
808 *
809 * The parameters used to derive the test data are:
810 *
811 * [AES-128 use df]
812 * [PredictionResistance = True/False]
813 * [EntropyInputLen = 128]
814 * [NonceLen = 64]
815 * [PersonalizationStringLen = 128]
816 * [AdditionalInputLen = 0]
817 * [ReturnedBitsLen = 512]
818 *
819 * [AES-256 use df]
820 * [PredictionResistance = True/False]
821 * [EntropyInputLen = 256]
822 * [NonceLen = 128]
823 * [PersonalizationStringLen = 256]
824 * [AdditionalInputLen = 0]
825 * [ReturnedBitsLen = 512]
826 *
827 */
828
Gilles Peskine02e79a42019-10-07 17:06:06 +0200829#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
ENT\stroej1df307002020-12-26 12:41:04 -0600830static const unsigned char entropy_source_pr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100831{ 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb,
832 0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92,
833 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8,
834 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20,
835 0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0,
836 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad,
837 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200838
ENT\stroej1df307002020-12-26 12:41:04 -0600839static const unsigned char entropy_source_nopr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100840{ 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45,
841 0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9,
842 0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20,
843 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f,
844 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c };
ENT\stroej1df307002020-12-26 12:41:04 -0600845
stroebeljcd4de1b52021-01-04 18:14:32 -0600846static const unsigned char pers_pr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100847{ 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a,
848 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad };
ENT\stroej1df307002020-12-26 12:41:04 -0600849
stroebeljcd4de1b52021-01-04 18:14:32 -0600850static const unsigned char pers_nopr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100851{ 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c,
852 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f };
ENT\stroej1df307002020-12-26 12:41:04 -0600853
854static const unsigned char result_pr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100855{ 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66,
856 0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff,
857 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10,
858 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30,
859 0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4,
860 0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc,
861 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06,
862 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf };
ENT\stroej1df307002020-12-26 12:41:04 -0600863
864static const unsigned char result_nopr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100865{ 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13,
866 0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0,
867 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf,
868 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2,
869 0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7,
870 0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2,
871 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02,
872 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200873#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000874
ENT\stroej1df307002020-12-26 12:41:04 -0600875static const unsigned char entropy_source_pr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100876{ 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49,
877 0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a,
878 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85,
879 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e,
880 0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15,
881 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45,
882 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8,
883 0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c,
884 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3,
885 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce,
886 0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e,
887 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76,
888 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77,
889 0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe };
ENT\stroej1df307002020-12-26 12:41:04 -0600890
891static const unsigned char entropy_source_nopr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100892{ 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d,
893 0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0,
894 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73,
895 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c,
896 0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2,
897 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1,
898 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a,
899 0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb,
900 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a,
901 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 };
ENT\stroej1df307002020-12-26 12:41:04 -0600902
stroebeljcd4de1b52021-01-04 18:14:32 -0600903static const unsigned char pers_pr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100904{ 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33,
905 0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e,
906 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0,
907 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 };
ENT\stroej1df307002020-12-26 12:41:04 -0600908
stroebeljcd4de1b52021-01-04 18:14:32 -0600909static const unsigned char pers_nopr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100910{ 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29,
911 0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf,
912 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb,
913 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b };
ENT\stroej1df307002020-12-26 12:41:04 -0600914
915static const unsigned char result_pr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100916{ 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85,
917 0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d,
918 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62,
919 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d,
920 0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb,
921 0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39,
922 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40,
923 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 };
ENT\stroej1df307002020-12-26 12:41:04 -0600924
925static const unsigned char result_nopr[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100926{ 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad,
927 0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3,
928 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b,
929 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14,
930 0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54,
931 0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30,
932 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a,
933 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200934#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000935
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100936static size_t test_offset;
Gilles Peskine449bd832023-01-11 14:50:10 +0100937static int ctr_drbg_self_test_entropy(void *data, unsigned char *buf,
938 size_t len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000939{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100940 const unsigned char *p = data;
Gilles Peskine449bd832023-01-11 14:50:10 +0100941 memcpy(buf, p + test_offset, len);
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100942 test_offset += len;
Gilles Peskine449bd832023-01-11 14:50:10 +0100943 return 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000944}
945
Gilles Peskine449bd832023-01-11 14:50:10 +0100946#define CHK(c) if ((c) != 0) \
947 { \
948 if (verbose != 0) \
949 mbedtls_printf("failed\n"); \
950 return 1; \
951 }
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100952
bootstrap-prime6dbbf442022-05-17 19:30:44 -0400953#define SELF_TEST_OUTPUT_DISCARD_LENGTH 64
stroebeljcd4de1b52021-01-04 18:14:32 -0600954
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000955/*
956 * Checkup routine
957 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100958int mbedtls_ctr_drbg_self_test(int verbose)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000959{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200960 mbedtls_ctr_drbg_context ctx;
Gilles Peskine449bd832023-01-11 14:50:10 +0100961 unsigned char buf[sizeof(result_pr)];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000962
Gilles Peskine449bd832023-01-11 14:50:10 +0100963 mbedtls_ctr_drbg_init(&ctx);
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200964
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000965 /*
966 * Based on a NIST CTR_DRBG test vector (PR = True)
967 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100968 if (verbose != 0) {
969 mbedtls_printf(" CTR_DRBG (PR = TRUE) : ");
970 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000971
972 test_offset = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100973 mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
974 mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2);
975 CHK(mbedtls_ctr_drbg_seed(&ctx,
976 ctr_drbg_self_test_entropy,
977 (void *) entropy_source_pr,
978 pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE));
979 mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_ON);
980 CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH));
981 CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_pr)));
982 CHK(memcmp(buf, result_pr, sizeof(result_pr)));
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000983
Gilles Peskine449bd832023-01-11 14:50:10 +0100984 mbedtls_ctr_drbg_free(&ctx);
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100985
Gilles Peskine449bd832023-01-11 14:50:10 +0100986 if (verbose != 0) {
987 mbedtls_printf("passed\n");
988 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000989
990 /*
991 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
992 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100993 if (verbose != 0) {
994 mbedtls_printf(" CTR_DRBG (PR = FALSE): ");
995 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000996
Gilles Peskine449bd832023-01-11 14:50:10 +0100997 mbedtls_ctr_drbg_init(&ctx);
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100998
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000999 test_offset = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +01001000 mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
1001 mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2);
1002 CHK(mbedtls_ctr_drbg_seed(&ctx,
1003 ctr_drbg_self_test_entropy,
1004 (void *) entropy_source_nopr,
1005 pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE));
1006 CHK(mbedtls_ctr_drbg_reseed(&ctx, NULL, 0));
1007 CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH));
1008 CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_nopr)));
1009 CHK(memcmp(buf, result_nopr, sizeof(result_nopr)));
Paul Bakker0e04d0e2011-11-27 14:46:59 +00001010
Gilles Peskine449bd832023-01-11 14:50:10 +01001011 mbedtls_ctr_drbg_free(&ctx);
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +01001012
Gilles Peskine449bd832023-01-11 14:50:10 +01001013 if (verbose != 0) {
1014 mbedtls_printf("passed\n");
1015 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +00001016
Gilles Peskine449bd832023-01-11 14:50:10 +01001017 if (verbose != 0) {
1018 mbedtls_printf("\n");
1019 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +00001020
Gilles Peskine449bd832023-01-11 14:50:10 +01001021 return 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +00001022}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001023#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +00001024
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001025#endif /* MBEDTLS_CTR_DRBG_C */