blob: 13fa6d4ebee16e541fb645ed265a1265bc7efbef [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
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakker0e04d0e2011-11-27 14:46:59 +000018 */
19/*
Paul Sokolovsky8d6d8c82018-02-10 11:11:41 +020020 * The NIST SP 800-90 DRBGs are described in the following publication.
Paul Bakker0e04d0e2011-11-27 14:46:59 +000021 *
22 * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
23 */
24
Gilles Peskinedb09ef62020-06-03 01:43:33 +020025#include "common.h"
Paul Bakker0e04d0e2011-11-27 14:46:59 +000026
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020027#if defined(MBEDTLS_CTR_DRBG_C)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000028
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000029#include "mbedtls/ctr_drbg.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050030#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000031#include "mbedtls/error.h"
Paul Bakker0e04d0e2011-11-27 14:46:59 +000032
Rich Evans00ab4702015-02-06 13:43:58 +000033#include <string.h>
34
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020035#if defined(MBEDTLS_FS_IO)
Paul Bakkerfc754a92011-12-05 13:23:51 +000036#include <stdio.h>
37#endif
38
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000039#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010040
Paul Bakker18d32912011-12-10 21:42:49 +000041/*
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020042 * CTR_DRBG context initialization
43 */
David Horstmann71159f42023-01-03 12:51:59 +000044void mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context *ctx)
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020045{
David Horstmann71159f42023-01-03 12:51:59 +000046 memset(ctx, 0, sizeof(mbedtls_ctr_drbg_context));
47 mbedtls_aes_init(&ctx->aes_ctx);
Gilles Peskinee9a34542019-10-22 20:43:24 +020048 /* Indicate that the entropy nonce length is not set explicitly.
49 * See mbedtls_ctr_drbg_set_nonce_len(). */
50 ctx->reseed_counter = -1;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010051
Gavin Acquroff6aceb512020-03-01 17:06:11 -080052 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020053}
54
Gavin Acquroff6aceb512020-03-01 17:06:11 -080055/*
56 * This function resets CTR_DRBG context to the state immediately
57 * after initial call of mbedtls_ctr_drbg_init().
58 */
David Horstmann71159f42023-01-03 12:51:59 +000059void mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context *ctx)
Paul Bakkerfff03662014-06-18 16:21:25 +020060{
David Horstmann71159f42023-01-03 12:51:59 +000061 if (ctx == NULL) {
Paul Bakkerfff03662014-06-18 16:21:25 +020062 return;
David Horstmann71159f42023-01-03 12:51:59 +000063 }
Paul Bakkerfff03662014-06-18 16:21:25 +020064
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010065#if defined(MBEDTLS_THREADING_C)
Gilles Peskineda290f92021-02-09 18:44:02 +010066 /* The mutex is initialized iff f_entropy is set. */
David Horstmann71159f42023-01-03 12:51:59 +000067 if (ctx->f_entropy != NULL) {
68 mbedtls_mutex_free(&ctx->mutex);
69 }
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010070#endif
David Horstmann71159f42023-01-03 12:51:59 +000071 mbedtls_aes_free(&ctx->aes_ctx);
72 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ctr_drbg_context));
Gavin Acquroff6aceb512020-03-01 17:06:11 -080073 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
74 ctx->reseed_counter = -1;
Paul Bakkerfff03662014-06-18 16:21:25 +020075}
76
David Horstmann71159f42023-01-03 12:51:59 +000077void mbedtls_ctr_drbg_set_prediction_resistance(mbedtls_ctr_drbg_context *ctx,
78 int resistance)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000079{
80 ctx->prediction_resistance = resistance;
81}
82
David Horstmann71159f42023-01-03 12:51:59 +000083void mbedtls_ctr_drbg_set_entropy_len(mbedtls_ctr_drbg_context *ctx,
84 size_t len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000085{
86 ctx->entropy_len = len;
87}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +020088
David Horstmann71159f42023-01-03 12:51:59 +000089int mbedtls_ctr_drbg_set_nonce_len(mbedtls_ctr_drbg_context *ctx,
90 size_t len)
Gilles Peskine9be50982019-10-22 18:42:27 +020091{
92 /* If mbedtls_ctr_drbg_seed() has already been called, it's
93 * too late. Return the error code that's closest to making sense. */
David Horstmann71159f42023-01-03 12:51:59 +000094 if (ctx->f_entropy != NULL) {
95 return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
96 }
Gilles Peskine9be50982019-10-22 18:42:27 +020097
David Horstmann71159f42023-01-03 12:51:59 +000098 if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
99 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
100 }
Gilles Peskine9be50982019-10-22 18:42:27 +0200101#if SIZE_MAX > INT_MAX
102 /* This shouldn't be an issue because
103 * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible
104 * configuration, but make sure anyway. */
David Horstmann71159f42023-01-03 12:51:59 +0000105 if (len > INT_MAX) {
106 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
107 }
Gilles Peskine9be50982019-10-22 18:42:27 +0200108#endif
109
110 /* For backward compatibility with Mbed TLS <= 2.19, store the
111 * entropy nonce length in a field that already exists, but isn't
112 * used until after the initial seeding. */
113 /* Due to the capping of len above, the value fits in an int. */
114 ctx->reseed_counter = (int) len;
David Horstmann71159f42023-01-03 12:51:59 +0000115 return 0;
Gilles Peskine9be50982019-10-22 18:42:27 +0200116}
117
David Horstmann71159f42023-01-03 12:51:59 +0000118void mbedtls_ctr_drbg_set_reseed_interval(mbedtls_ctr_drbg_context *ctx,
119 int interval)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000120{
121 ctx->reseed_interval = interval;
122}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200123
David Horstmann71159f42023-01-03 12:51:59 +0000124static int block_cipher_df(unsigned char *output,
125 const unsigned char *data, size_t data_len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000126{
Hanno Beckera08651f2018-10-05 09:38:59 +0100127 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
128 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200129 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
130 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
131 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100132 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200133 mbedtls_aes_context aes_ctx;
Dvir Markovich1b364992017-06-26 13:43:34 +0300134 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000135
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200136 int i, j;
137 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000138
David Horstmann71159f42023-01-03 12:51:59 +0000139 if (data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
140 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
141 }
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100142
David Horstmann71159f42023-01-03 12:51:59 +0000143 memset(buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
144 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16);
145 mbedtls_aes_init(&aes_ctx);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000146
147 /*
148 * Construct IV (16 bytes) and S in buffer
149 * IV = Counter (in 32-bits) padded to 16 with zeroes
150 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
151 * data || 0x80
152 * (Total is padded to a multiple of 16-bytes with zeroes)
153 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200154 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
David Horstmann71159f42023-01-03 12:51:59 +0000155 MBEDTLS_PUT_UINT32_BE(data_len, p, 0);
Joe Subbiania5cb0d22021-08-23 11:35:25 +0100156 p += 4 + 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200157 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
David Horstmann71159f42023-01-03 12:51:59 +0000158 memcpy(p, data, data_len);
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000159 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000160
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200161 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000162
David Horstmann71159f42023-01-03 12:51:59 +0000163 for (i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000164 key[i] = i;
David Horstmann71159f42023-01-03 12:51:59 +0000165 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000166
David Horstmann71159f42023-01-03 12:51:59 +0000167 if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, key,
168 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300169 goto exit;
170 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000171
172 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200173 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000174 */
David Horstmann71159f42023-01-03 12:51:59 +0000175 for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000176 p = buf;
David Horstmann71159f42023-01-03 12:51:59 +0000177 memset(chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000178 use_len = buf_len;
179
David Horstmann71159f42023-01-03 12:51:59 +0000180 while (use_len > 0) {
181 mbedtls_xor(chain, chain, p, MBEDTLS_CTR_DRBG_BLOCKSIZE);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200182 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
David Horstmann71159f42023-01-03 12:51:59 +0000183 use_len -= (use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE) ?
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200184 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000185
David Horstmann71159f42023-01-03 12:51:59 +0000186 if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,
187 chain, chain)) != 0) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300188 goto exit;
189 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000190 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200191
David Horstmann71159f42023-01-03 12:51:59 +0000192 memcpy(tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000193
194 /*
195 * Update IV
196 */
197 buf[3]++;
198 }
199
200 /*
201 * Do final encryption with reduced data
202 */
David Horstmann71159f42023-01-03 12:51:59 +0000203 if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, tmp,
204 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300205 goto exit;
206 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200207 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000208 p = output;
209
David Horstmann71159f42023-01-03 12:51:59 +0000210 for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
211 if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,
212 iv, iv)) != 0) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300213 goto exit;
214 }
David Horstmann71159f42023-01-03 12:51:59 +0000215 memcpy(p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200216 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000217 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300218exit:
David Horstmann71159f42023-01-03 12:51:59 +0000219 mbedtls_aes_free(&aes_ctx);
Dvir Markovich1b364992017-06-26 13:43:34 +0300220 /*
David Horstmann71159f42023-01-03 12:51:59 +0000221 * tidy up the stack
222 */
223 mbedtls_platform_zeroize(buf, sizeof(buf));
224 mbedtls_platform_zeroize(tmp, sizeof(tmp));
225 mbedtls_platform_zeroize(key, sizeof(key));
226 mbedtls_platform_zeroize(chain, sizeof(chain));
227 if (0 != ret) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300228 /*
David Horstmann71159f42023-01-03 12:51:59 +0000229 * wipe partial seed from memory
230 */
231 mbedtls_platform_zeroize(output, MBEDTLS_CTR_DRBG_SEEDLEN);
Dvir Markovich1b364992017-06-26 13:43:34 +0300232 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200233
David Horstmann71159f42023-01-03 12:51:59 +0000234 return ret;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000235}
236
Gilles Peskineed7da592018-08-03 20:16:52 +0200237/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
238 * ctr_drbg_update_internal(ctx, provided_data)
239 * implements
240 * CTR_DRBG_Update(provided_data, Key, V)
241 * with inputs and outputs
242 * ctx->aes_ctx = Key
243 * ctx->counter = V
244 */
David Horstmann71159f42023-01-03 12:51:59 +0000245static int ctr_drbg_update_internal(mbedtls_ctr_drbg_context *ctx,
246 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN])
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000247{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200248 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000249 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000250 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300251 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000252
David Horstmann71159f42023-01-03 12:51:59 +0000253 memset(tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000254
David Horstmann71159f42023-01-03 12:51:59 +0000255 for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000256 /*
257 * Increase counter
258 */
David Horstmann71159f42023-01-03 12:51:59 +0000259 for (i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i--) {
260 if (++ctx->counter[i - 1] != 0) {
Paul Bakker369e14b2012-04-18 14:16:09 +0000261 break;
David Horstmann71159f42023-01-03 12:51:59 +0000262 }
263 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000264
265 /*
266 * Crypt counter block
267 */
David Horstmann71159f42023-01-03 12:51:59 +0000268 if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
269 ctx->counter, p)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200270 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300271 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000272
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200273 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000274 }
275
David Horstmann71159f42023-01-03 12:51:59 +0000276 for (i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000277 tmp[i] ^= data[i];
David Horstmann71159f42023-01-03 12:51:59 +0000278 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000279
280 /*
281 * Update key and counter
282 */
David Horstmann71159f42023-01-03 12:51:59 +0000283 if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, tmp,
284 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200285 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300286 }
David Horstmann71159f42023-01-03 12:51:59 +0000287 memcpy(ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
288 MBEDTLS_CTR_DRBG_BLOCKSIZE);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000289
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200290exit:
David Horstmann71159f42023-01-03 12:51:59 +0000291 mbedtls_platform_zeroize(tmp, sizeof(tmp));
292 return ret;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000293}
294
Gilles Peskineed7da592018-08-03 20:16:52 +0200295/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
TRodziewicz26371e42021-06-08 16:45:41 +0200296 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
Gilles Peskineed7da592018-08-03 20:16:52 +0200297 * implements
298 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
299 * security_strength) -> initial_working_state
300 * with inputs
301 * ctx->counter = all-bits-0
302 * ctx->aes_ctx = context from all-bits-0 key
303 * additional[:add_len] = entropy_input || nonce || personalization_string
304 * and with outputs
305 * ctx = initial_working_state
306 */
David Horstmann71159f42023-01-03 12:51:59 +0000307int mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context *ctx,
308 const unsigned char *additional,
309 size_t add_len)
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000310{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200311 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Janos Follath24eed8d2019-11-22 13:21:35 +0000312 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000313
David Horstmann71159f42023-01-03 12:51:59 +0000314 if (add_len == 0) {
315 return 0;
316 }
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100317
David Horstmann71159f42023-01-03 12:51:59 +0000318 if ((ret = block_cipher_df(add_input, additional, add_len)) != 0) {
Gilles Peskined9199932018-09-11 16:41:54 +0200319 goto exit;
David Horstmann71159f42023-01-03 12:51:59 +0000320 }
321 if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {
Gilles Peskined9199932018-09-11 16:41:54 +0200322 goto exit;
David Horstmann71159f42023-01-03 12:51:59 +0000323 }
Gilles Peskined9199932018-09-11 16:41:54 +0200324
325exit:
David Horstmann71159f42023-01-03 12:51:59 +0000326 mbedtls_platform_zeroize(add_input, sizeof(add_input));
327 return ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000328}
329
Gilles Peskineed7da592018-08-03 20:16:52 +0200330/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
Gilles Peskine9be50982019-10-22 18:42:27 +0200331 * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
Gilles Peskineed7da592018-08-03 20:16:52 +0200332 * implements
333 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
334 * -> new_working_state
335 * with inputs
336 * ctx contains working_state
337 * additional[:len] = additional_input
338 * and entropy_input comes from calling ctx->f_entropy
Gilles Peskine9be50982019-10-22 18:42:27 +0200339 * for (ctx->entropy_len + nonce_len) bytes
Gilles Peskineed7da592018-08-03 20:16:52 +0200340 * and with output
341 * ctx contains new_working_state
342 */
David Horstmann71159f42023-01-03 12:51:59 +0000343static int mbedtls_ctr_drbg_reseed_internal(mbedtls_ctr_drbg_context *ctx,
344 const unsigned char *additional,
345 size_t len,
346 size_t nonce_len)
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000347{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200348 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000349 size_t seedlen = 0;
Janos Follath24eed8d2019-11-22 13:21:35 +0000350 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000351
David Horstmann71159f42023-01-03 12:51:59 +0000352 if (ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
353 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
354 }
355 if (nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len) {
356 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
357 }
358 if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len) {
359 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
360 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000361
David Horstmann71159f42023-01-03 12:51:59 +0000362 memset(seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT);
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000363
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200364 /* Gather entropy_len bytes of entropy to seed state. */
David Horstmann71159f42023-01-03 12:51:59 +0000365 if (0 != ctx->f_entropy(ctx->p_entropy, seed, ctx->entropy_len)) {
366 return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000367 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000368 seedlen += ctx->entropy_len;
369
Gilles Peskine9be50982019-10-22 18:42:27 +0200370 /* Gather entropy for a nonce if requested. */
David Horstmann71159f42023-01-03 12:51:59 +0000371 if (nonce_len != 0) {
372 if (0 != ctx->f_entropy(ctx->p_entropy, seed + seedlen, nonce_len)) {
373 return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
Gilles Peskine9be50982019-10-22 18:42:27 +0200374 }
375 seedlen += nonce_len;
376 }
377
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200378 /* Add additional data if provided. */
David Horstmann71159f42023-01-03 12:51:59 +0000379 if (additional != NULL && len != 0) {
380 memcpy(seed + seedlen, additional, len);
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000381 seedlen += len;
382 }
383
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200384 /* Reduce to 384 bits. */
David Horstmann71159f42023-01-03 12:51:59 +0000385 if ((ret = block_cipher_df(seed, seed, seedlen)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200386 goto exit;
David Horstmann71159f42023-01-03 12:51:59 +0000387 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000388
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200389 /* Update state. */
David Horstmann71159f42023-01-03 12:51:59 +0000390 if ((ret = ctr_drbg_update_internal(ctx, seed)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200391 goto exit;
David Horstmann71159f42023-01-03 12:51:59 +0000392 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000393 ctx->reseed_counter = 1;
394
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200395exit:
David Horstmann71159f42023-01-03 12:51:59 +0000396 mbedtls_platform_zeroize(seed, sizeof(seed));
397 return ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000398}
Paul Bakker9af723c2014-05-01 13:03:14 +0200399
David Horstmann71159f42023-01-03 12:51:59 +0000400int mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context *ctx,
401 const unsigned char *additional, size_t len)
Gilles Peskine9be50982019-10-22 18:42:27 +0200402{
David Horstmann71159f42023-01-03 12:51:59 +0000403 return mbedtls_ctr_drbg_reseed_internal(ctx, additional, len, 0);
Gilles Peskine9be50982019-10-22 18:42:27 +0200404}
405
Gilles Peskinee9a34542019-10-22 20:43:24 +0200406/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
407 * is sufficient to achieve the maximum security strength given the key
408 * size and entropy length. If there is enough entropy in the initial
409 * call to the entropy function to serve as both the entropy input and
410 * the nonce, don't make a second call to get a nonce. */
David Horstmann71159f42023-01-03 12:51:59 +0000411static size_t good_nonce_len(size_t entropy_len)
Gilles Peskinee9a34542019-10-22 20:43:24 +0200412{
David Horstmann71159f42023-01-03 12:51:59 +0000413 if (entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2) {
414 return 0;
415 } else {
416 return (entropy_len + 1) / 2;
417 }
Gilles Peskinee9a34542019-10-22 20:43:24 +0200418}
419
Gilles Peskine8bf56132019-10-02 20:31:54 +0200420/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
Gilles Peskine379561f2019-10-18 16:57:48 +0200421 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
Gilles Peskine8bf56132019-10-02 20:31:54 +0200422 * implements
423 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
424 * security_strength) -> initial_working_state
425 * with inputs
426 * custom[:len] = nonce || personalization_string
Gilles Peskine379561f2019-10-18 16:57:48 +0200427 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
Gilles Peskine8bf56132019-10-02 20:31:54 +0200428 * and with outputs
429 * ctx = initial_working_state
430 */
David Horstmann71159f42023-01-03 12:51:59 +0000431int mbedtls_ctr_drbg_seed(mbedtls_ctr_drbg_context *ctx,
432 int (*f_entropy)(void *, unsigned char *, size_t),
433 void *p_entropy,
434 const unsigned char *custom,
435 size_t len)
Gilles Peskine8bf56132019-10-02 20:31:54 +0200436{
Janos Follath24eed8d2019-11-22 13:21:35 +0000437 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200438 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Gilles Peskinee9a34542019-10-22 20:43:24 +0200439 size_t nonce_len;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200440
David Horstmann71159f42023-01-03 12:51:59 +0000441 memset(key, 0, MBEDTLS_CTR_DRBG_KEYSIZE);
Gilles Peskine8bf56132019-10-02 20:31:54 +0200442
Gilles Peskineda290f92021-02-09 18:44:02 +0100443 /* The mutex is initialized iff f_entropy is set. */
Gilles Peskinef4b34292021-01-30 13:05:32 +0100444#if defined(MBEDTLS_THREADING_C)
David Horstmann71159f42023-01-03 12:51:59 +0000445 mbedtls_mutex_init(&ctx->mutex);
Gilles Peskinef4b34292021-01-30 13:05:32 +0100446#endif
447
Gilles Peskine8bf56132019-10-02 20:31:54 +0200448 ctx->f_entropy = f_entropy;
449 ctx->p_entropy = p_entropy;
450
David Horstmann71159f42023-01-03 12:51:59 +0000451 if (ctx->entropy_len == 0) {
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200452 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
David Horstmann71159f42023-01-03 12:51:59 +0000453 }
Gilles Peskinee9a34542019-10-22 20:43:24 +0200454 /* ctx->reseed_counter contains the desired amount of entropy to
455 * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
456 * If it's -1, indicating that the entropy nonce length was not set
457 * explicitly, use a sufficiently large nonce for security. */
David Horstmann71159f42023-01-03 12:51:59 +0000458 nonce_len = (ctx->reseed_counter >= 0 ?
459 (size_t) ctx->reseed_counter :
460 good_nonce_len(ctx->entropy_len));
Gilles Peskinee9a34542019-10-22 20:43:24 +0200461
Gilles Peskine9be50982019-10-22 18:42:27 +0200462 /* Initialize with an empty key. */
David Horstmann71159f42023-01-03 12:51:59 +0000463 if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, key,
464 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
465 return ret;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200466 }
467
Gilles Peskinee9a34542019-10-22 20:43:24 +0200468 /* Do the initial seeding. */
David Horstmann71159f42023-01-03 12:51:59 +0000469 if ((ret = mbedtls_ctr_drbg_reseed_internal(ctx, custom, len,
470 nonce_len)) != 0) {
471 return ret;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200472 }
David Horstmann71159f42023-01-03 12:51:59 +0000473 return 0;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200474}
475
Gilles Peskineed7da592018-08-03 20:16:52 +0200476/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
477 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
478 * implements
479 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
480 * -> working_state_after_reseed
481 * if required, then
482 * CTR_DRBG_Generate(working_state_after_reseed,
483 * requested_number_of_bits, additional_input)
484 * -> status, returned_bits, new_working_state
485 * with inputs
486 * ctx contains working_state
487 * requested_number_of_bits = 8 * output_len
488 * additional[:add_len] = additional_input
489 * and entropy_input comes from calling ctx->f_entropy
490 * and with outputs
491 * status = SUCCESS (this function does the reseed internally)
492 * returned_bits = output[:output_len]
493 * ctx contains new_working_state
494 */
David Horstmann71159f42023-01-03 12:51:59 +0000495int mbedtls_ctr_drbg_random_with_add(void *p_rng,
496 unsigned char *output, size_t output_len,
497 const unsigned char *additional, size_t add_len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000498{
499 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200500 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
501 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000502 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200503 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000504 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000505 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000506
David Horstmann71159f42023-01-03 12:51:59 +0000507 if (output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST) {
508 return MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG;
509 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000510
David Horstmann71159f42023-01-03 12:51:59 +0000511 if (add_len > MBEDTLS_CTR_DRBG_MAX_INPUT) {
512 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
513 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000514
David Horstmann71159f42023-01-03 12:51:59 +0000515 memset(add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000516
David Horstmann71159f42023-01-03 12:51:59 +0000517 if (ctx->reseed_counter > ctx->reseed_interval ||
518 ctx->prediction_resistance) {
519 if ((ret = mbedtls_ctr_drbg_reseed(ctx, additional, add_len)) != 0) {
520 return ret;
Dvir Markovich1b364992017-06-26 13:43:34 +0300521 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000522 add_len = 0;
523 }
524
David Horstmann71159f42023-01-03 12:51:59 +0000525 if (add_len > 0) {
526 if ((ret = block_cipher_df(add_input, additional, add_len)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200527 goto exit;
David Horstmann71159f42023-01-03 12:51:59 +0000528 }
529 if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200530 goto exit;
David Horstmann71159f42023-01-03 12:51:59 +0000531 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000532 }
533
David Horstmann71159f42023-01-03 12:51:59 +0000534 while (output_len > 0) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000535 /*
536 * Increase counter
537 */
David Horstmann71159f42023-01-03 12:51:59 +0000538 for (i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i--) {
539 if (++ctx->counter[i - 1] != 0) {
Paul Bakker369e14b2012-04-18 14:16:09 +0000540 break;
David Horstmann71159f42023-01-03 12:51:59 +0000541 }
542 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000543
544 /*
545 * Crypt counter block
546 */
David Horstmann71159f42023-01-03 12:51:59 +0000547 if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
548 ctx->counter, tmp)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200549 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300550 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000551
David Horstmann71159f42023-01-03 12:51:59 +0000552 use_len = (output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE)
Hanno Beckera08651f2018-10-05 09:38:59 +0100553 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000554 /*
555 * Copy random block to destination
556 */
David Horstmann71159f42023-01-03 12:51:59 +0000557 memcpy(p, tmp, use_len);
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000558 p += use_len;
559 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000560 }
561
David Horstmann71159f42023-01-03 12:51:59 +0000562 if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200563 goto exit;
David Horstmann71159f42023-01-03 12:51:59 +0000564 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000565
566 ctx->reseed_counter++;
567
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200568exit:
David Horstmann71159f42023-01-03 12:51:59 +0000569 mbedtls_platform_zeroize(add_input, sizeof(add_input));
570 mbedtls_platform_zeroize(tmp, sizeof(tmp));
571 return ret;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000572}
573
David Horstmann71159f42023-01-03 12:51:59 +0000574int mbedtls_ctr_drbg_random(void *p_rng, unsigned char *output,
575 size_t output_len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000576{
Janos Follath24eed8d2019-11-22 13:21:35 +0000577 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100578 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
579
580#if defined(MBEDTLS_THREADING_C)
David Horstmann71159f42023-01-03 12:51:59 +0000581 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
582 return ret;
583 }
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100584#endif
585
David Horstmann71159f42023-01-03 12:51:59 +0000586 ret = mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, NULL, 0);
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100587
588#if defined(MBEDTLS_THREADING_C)
David Horstmann71159f42023-01-03 12:51:59 +0000589 if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
590 return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
591 }
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100592#endif
593
David Horstmann71159f42023-01-03 12:51:59 +0000594 return ret;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000595}
596
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200597#if defined(MBEDTLS_FS_IO)
David Horstmann71159f42023-01-03 12:51:59 +0000598int mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context *ctx,
599 const char *path)
Paul Bakkerfc754a92011-12-05 13:23:51 +0000600{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200601 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000602 FILE *f;
David Horstmann71159f42023-01-03 12:51:59 +0000603 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000604
David Horstmann71159f42023-01-03 12:51:59 +0000605 if ((f = fopen(path, "wb")) == NULL) {
606 return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
607 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000608
Gilles Peskineda0913b2022-06-30 17:03:40 +0200609 /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
David Horstmann71159f42023-01-03 12:51:59 +0000610 mbedtls_setbuf(f, NULL);
Gilles Peskineda0913b2022-06-30 17:03:40 +0200611
David Horstmann71159f42023-01-03 12:51:59 +0000612 if ((ret = mbedtls_ctr_drbg_random(ctx, buf,
613 MBEDTLS_CTR_DRBG_MAX_INPUT)) != 0) {
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200614 goto exit;
Hanno Beckera08651f2018-10-05 09:38:59 +0100615 }
David Horstmann71159f42023-01-03 12:51:59 +0000616
617 if (fwrite(buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f) !=
618 MBEDTLS_CTR_DRBG_MAX_INPUT) {
619 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
620 } else {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100621 ret = 0;
Hanno Beckera08651f2018-10-05 09:38:59 +0100622 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000623
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100624exit:
David Horstmann71159f42023-01-03 12:51:59 +0000625 mbedtls_platform_zeroize(buf, sizeof(buf));
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200626
David Horstmann71159f42023-01-03 12:51:59 +0000627 fclose(f);
628 return ret;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000629}
630
David Horstmann71159f42023-01-03 12:51:59 +0000631int mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context *ctx,
632 const char *path)
Paul Bakkerfc754a92011-12-05 13:23:51 +0000633{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100634 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200635 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000636 size_t n;
David Horstmann71159f42023-01-03 12:51:59 +0000637 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT];
Gilles Peskine82204662018-09-11 18:43:09 +0200638 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000639
David Horstmann71159f42023-01-03 12:51:59 +0000640 if ((f = fopen(path, "rb")) == NULL) {
641 return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
642 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000643
Gilles Peskineda0913b2022-06-30 17:03:40 +0200644 /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
David Horstmann71159f42023-01-03 12:51:59 +0000645 mbedtls_setbuf(f, NULL);
Gilles Peskineda0913b2022-06-30 17:03:40 +0200646
David Horstmann71159f42023-01-03 12:51:59 +0000647 n = fread(buf, 1, sizeof(buf), f);
648 if (fread(&c, 1, 1, f) != 0) {
Gilles Peskine82204662018-09-11 18:43:09 +0200649 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
650 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100651 }
David Horstmann71159f42023-01-03 12:51:59 +0000652 if (n == 0 || ferror(f)) {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100653 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200654 goto exit;
655 }
David Horstmann71159f42023-01-03 12:51:59 +0000656 fclose(f);
Gilles Peskine82204662018-09-11 18:43:09 +0200657 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200658
David Horstmann71159f42023-01-03 12:51:59 +0000659 ret = mbedtls_ctr_drbg_update(ctx, buf, n);
Gilles Peskine82204662018-09-11 18:43:09 +0200660
661exit:
David Horstmann71159f42023-01-03 12:51:59 +0000662 mbedtls_platform_zeroize(buf, sizeof(buf));
663 if (f != NULL) {
664 fclose(f);
665 }
666 if (ret != 0) {
667 return ret;
668 }
669 return mbedtls_ctr_drbg_write_seed_file(ctx, path);
Paul Bakkerfc754a92011-12-05 13:23:51 +0000670}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200671#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000672
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200673#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000674
ENT\stroej170f63d02020-12-28 08:50:23 -0600675/* The CTR_DRBG NIST test vectors used here are available at
676 * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip
677 *
678 * The parameters used to derive the test data are:
679 *
680 * [AES-128 use df]
681 * [PredictionResistance = True/False]
682 * [EntropyInputLen = 128]
683 * [NonceLen = 64]
684 * [PersonalizationStringLen = 128]
685 * [AdditionalInputLen = 0]
686 * [ReturnedBitsLen = 512]
687 *
688 * [AES-256 use df]
689 * [PredictionResistance = True/False]
690 * [EntropyInputLen = 256]
691 * [NonceLen = 128]
692 * [PersonalizationStringLen = 256]
693 * [AdditionalInputLen = 0]
694 * [ReturnedBitsLen = 512]
695 *
696 */
697
Gilles Peskine02e79a42019-10-07 17:06:06 +0200698#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
ENT\stroej1df307002020-12-26 12:41:04 -0600699static const unsigned char entropy_source_pr[] =
David Horstmann71159f42023-01-03 12:51:59 +0000700{ 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb,
701 0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92,
702 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8,
703 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20,
704 0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0,
705 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad,
706 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200707
ENT\stroej1df307002020-12-26 12:41:04 -0600708static const unsigned char entropy_source_nopr[] =
David Horstmann71159f42023-01-03 12:51:59 +0000709{ 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45,
710 0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9,
711 0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20,
712 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f,
713 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c };
ENT\stroej1df307002020-12-26 12:41:04 -0600714
stroebeljcd4de1b52021-01-04 18:14:32 -0600715static const unsigned char pers_pr[] =
David Horstmann71159f42023-01-03 12:51:59 +0000716{ 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a,
717 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad };
ENT\stroej1df307002020-12-26 12:41:04 -0600718
stroebeljcd4de1b52021-01-04 18:14:32 -0600719static const unsigned char pers_nopr[] =
David Horstmann71159f42023-01-03 12:51:59 +0000720{ 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c,
721 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f };
ENT\stroej1df307002020-12-26 12:41:04 -0600722
723static const unsigned char result_pr[] =
David Horstmann71159f42023-01-03 12:51:59 +0000724{ 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66,
725 0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff,
726 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10,
727 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30,
728 0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4,
729 0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc,
730 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06,
731 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf };
ENT\stroej1df307002020-12-26 12:41:04 -0600732
733static const unsigned char result_nopr[] =
David Horstmann71159f42023-01-03 12:51:59 +0000734{ 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13,
735 0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0,
736 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf,
737 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2,
738 0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7,
739 0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2,
740 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02,
741 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200742#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000743
ENT\stroej1df307002020-12-26 12:41:04 -0600744static const unsigned char entropy_source_pr[] =
David Horstmann71159f42023-01-03 12:51:59 +0000745{ 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49,
746 0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a,
747 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85,
748 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e,
749 0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15,
750 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45,
751 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8,
752 0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c,
753 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3,
754 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce,
755 0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e,
756 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76,
757 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77,
758 0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe };
ENT\stroej1df307002020-12-26 12:41:04 -0600759
760static const unsigned char entropy_source_nopr[] =
David Horstmann71159f42023-01-03 12:51:59 +0000761{ 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d,
762 0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0,
763 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73,
764 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c,
765 0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2,
766 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1,
767 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a,
768 0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb,
769 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a,
770 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 };
ENT\stroej1df307002020-12-26 12:41:04 -0600771
stroebeljcd4de1b52021-01-04 18:14:32 -0600772static const unsigned char pers_pr[] =
David Horstmann71159f42023-01-03 12:51:59 +0000773{ 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33,
774 0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e,
775 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0,
776 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 };
ENT\stroej1df307002020-12-26 12:41:04 -0600777
stroebeljcd4de1b52021-01-04 18:14:32 -0600778static const unsigned char pers_nopr[] =
David Horstmann71159f42023-01-03 12:51:59 +0000779{ 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29,
780 0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf,
781 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb,
782 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b };
ENT\stroej1df307002020-12-26 12:41:04 -0600783
784static const unsigned char result_pr[] =
David Horstmann71159f42023-01-03 12:51:59 +0000785{ 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85,
786 0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d,
787 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62,
788 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d,
789 0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb,
790 0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39,
791 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40,
792 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 };
ENT\stroej1df307002020-12-26 12:41:04 -0600793
794static const unsigned char result_nopr[] =
David Horstmann71159f42023-01-03 12:51:59 +0000795{ 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad,
796 0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3,
797 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b,
798 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14,
799 0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54,
800 0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30,
801 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a,
802 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200803#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000804
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100805static size_t test_offset;
David Horstmann71159f42023-01-03 12:51:59 +0000806static int ctr_drbg_self_test_entropy(void *data, unsigned char *buf,
807 size_t len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000808{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100809 const unsigned char *p = data;
David Horstmann71159f42023-01-03 12:51:59 +0000810 memcpy(buf, p + test_offset, len);
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100811 test_offset += len;
David Horstmann71159f42023-01-03 12:51:59 +0000812 return 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000813}
814
David Horstmann71159f42023-01-03 12:51:59 +0000815#define CHK(c) if ((c) != 0) \
816 { \
817 if (verbose != 0) \
818 mbedtls_printf("failed\n"); \
819 return 1; \
820 }
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100821
bootstrap-prime6dbbf442022-05-17 19:30:44 -0400822#define SELF_TEST_OUTPUT_DISCARD_LENGTH 64
stroebeljcd4de1b52021-01-04 18:14:32 -0600823
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000824/*
825 * Checkup routine
826 */
David Horstmann71159f42023-01-03 12:51:59 +0000827int mbedtls_ctr_drbg_self_test(int verbose)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000828{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200829 mbedtls_ctr_drbg_context ctx;
David Horstmann71159f42023-01-03 12:51:59 +0000830 unsigned char buf[sizeof(result_pr)];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000831
David Horstmann71159f42023-01-03 12:51:59 +0000832 mbedtls_ctr_drbg_init(&ctx);
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200833
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000834 /*
835 * Based on a NIST CTR_DRBG test vector (PR = True)
836 */
David Horstmann71159f42023-01-03 12:51:59 +0000837 if (verbose != 0) {
838 mbedtls_printf(" CTR_DRBG (PR = TRUE) : ");
839 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000840
841 test_offset = 0;
David Horstmann71159f42023-01-03 12:51:59 +0000842 mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
843 mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2);
844 CHK(mbedtls_ctr_drbg_seed(&ctx,
845 ctr_drbg_self_test_entropy,
846 (void *) entropy_source_pr,
847 pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE));
848 mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_ON);
849 CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH));
850 CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_pr)));
851 CHK(memcmp(buf, result_pr, sizeof(result_pr)));
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000852
David Horstmann71159f42023-01-03 12:51:59 +0000853 mbedtls_ctr_drbg_free(&ctx);
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100854
David Horstmann71159f42023-01-03 12:51:59 +0000855 if (verbose != 0) {
856 mbedtls_printf("passed\n");
857 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000858
859 /*
860 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
861 */
David Horstmann71159f42023-01-03 12:51:59 +0000862 if (verbose != 0) {
863 mbedtls_printf(" CTR_DRBG (PR = FALSE): ");
864 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000865
David Horstmann71159f42023-01-03 12:51:59 +0000866 mbedtls_ctr_drbg_init(&ctx);
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100867
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000868 test_offset = 0;
David Horstmann71159f42023-01-03 12:51:59 +0000869 mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
870 mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2);
871 CHK(mbedtls_ctr_drbg_seed(&ctx,
872 ctr_drbg_self_test_entropy,
873 (void *) entropy_source_nopr,
874 pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE));
875 CHK(mbedtls_ctr_drbg_reseed(&ctx, NULL, 0));
876 CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH));
877 CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_nopr)));
878 CHK(memcmp(buf, result_nopr, sizeof(result_nopr)));
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000879
David Horstmann71159f42023-01-03 12:51:59 +0000880 mbedtls_ctr_drbg_free(&ctx);
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100881
David Horstmann71159f42023-01-03 12:51:59 +0000882 if (verbose != 0) {
883 mbedtls_printf("passed\n");
884 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000885
David Horstmann71159f42023-01-03 12:51:59 +0000886 if (verbose != 0) {
887 mbedtls_printf("\n");
888 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000889
David Horstmann71159f42023-01-03 12:51:59 +0000890 return 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000891}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200892#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000893
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200894#endif /* MBEDTLS_CTR_DRBG_C */