blob: f32e71e5c0c0d8173695e9eadf12b9f27361e6c3 [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
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020029# include "mbedtls/ctr_drbg.h"
30# include "mbedtls/platform_util.h"
31# include "mbedtls/error.h"
Paul Bakker0e04d0e2011-11-27 14:46:59 +000032
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020033# include <string.h>
Rich Evans00ab4702015-02-06 13:43:58 +000034
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020035# if defined(MBEDTLS_FS_IO)
36# include <stdio.h>
37# endif
Paul Bakkerfc754a92011-12-05 13:23:51 +000038
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020039# if defined(MBEDTLS_SELF_TEST)
40# if defined(MBEDTLS_PLATFORM_C)
41# include "mbedtls/platform.h"
42# else
43# include <stdio.h>
44# define mbedtls_printf printf
45# endif /* MBEDTLS_PLATFORM_C */
46# endif /* MBEDTLS_SELF_TEST */
Paul Bakker7dc4c442014-02-01 22:50:26 +010047
Paul Bakker18d32912011-12-10 21:42:49 +000048/*
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020049 * CTR_DRBG context initialization
50 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020051void mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context *ctx)
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020052{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020053 memset(ctx, 0, sizeof(mbedtls_ctr_drbg_context));
Gilles Peskinee9a34542019-10-22 20:43:24 +020054 /* Indicate that the entropy nonce length is not set explicitly.
55 * See mbedtls_ctr_drbg_set_nonce_len(). */
56 ctx->reseed_counter = -1;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010057
Gavin Acquroff6aceb512020-03-01 17:06:11 -080058 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020059}
60
Gavin Acquroff6aceb512020-03-01 17:06:11 -080061/*
62 * This function resets CTR_DRBG context to the state immediately
63 * after initial call of mbedtls_ctr_drbg_init().
64 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020065void mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context *ctx)
Paul Bakkerfff03662014-06-18 16:21:25 +020066{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020067 if (ctx == NULL)
Paul Bakkerfff03662014-06-18 16:21:25 +020068 return;
69
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020070# if defined(MBEDTLS_THREADING_C)
Gilles Peskineda290f92021-02-09 18:44:02 +010071 /* The mutex is initialized iff f_entropy is set. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020072 if (ctx->f_entropy != NULL)
73 mbedtls_mutex_free(&ctx->mutex);
74# endif
75 mbedtls_aes_free(&ctx->aes_ctx);
76 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ctr_drbg_context));
Gavin Acquroff6aceb512020-03-01 17:06:11 -080077 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
78 ctx->reseed_counter = -1;
Paul Bakkerfff03662014-06-18 16:21:25 +020079}
80
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020081void mbedtls_ctr_drbg_set_prediction_resistance(mbedtls_ctr_drbg_context *ctx,
82 int resistance)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000083{
84 ctx->prediction_resistance = resistance;
85}
86
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020087void mbedtls_ctr_drbg_set_entropy_len(mbedtls_ctr_drbg_context *ctx, size_t len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000088{
89 ctx->entropy_len = len;
90}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +020091
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020092int mbedtls_ctr_drbg_set_nonce_len(mbedtls_ctr_drbg_context *ctx, size_t len)
Gilles Peskine9be50982019-10-22 18:42:27 +020093{
94 /* If mbedtls_ctr_drbg_seed() has already been called, it's
95 * too late. Return the error code that's closest to making sense. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020096 if (ctx->f_entropy != NULL)
97 return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
Gilles Peskine9be50982019-10-22 18:42:27 +020098
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020099 if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT)
100 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
101# if SIZE_MAX > INT_MAX
Gilles Peskine9be50982019-10-22 18:42:27 +0200102 /* 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. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200105 if (len > INT_MAX)
106 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
107# endif
Gilles Peskine9be50982019-10-22 18:42:27 +0200108
109 /* For backward compatibility with Mbed TLS <= 2.19, store the
110 * entropy nonce length in a field that already exists, but isn't
111 * used until after the initial seeding. */
112 /* Due to the capping of len above, the value fits in an int. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200113 ctx->reseed_counter = (int)len;
114 return 0;
Gilles Peskine9be50982019-10-22 18:42:27 +0200115}
116
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200117void mbedtls_ctr_drbg_set_reseed_interval(mbedtls_ctr_drbg_context *ctx,
118 int interval)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000119{
120 ctx->reseed_interval = interval;
121}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200122
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200123static int block_cipher_df(unsigned char *output,
124 const unsigned char *data,
125 size_t data_len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000126{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200127 unsigned char
128 buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + 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
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200139 if (data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT)
140 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100141
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200142 memset(buf, 0,
143 MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16);
144 mbedtls_aes_init(&aes_ctx);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000145
146 /*
147 * Construct IV (16 bytes) and S in buffer
148 * IV = Counter (in 32-bits) padded to 16 with zeroes
149 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
150 * data || 0x80
151 * (Total is padded to a multiple of 16-bytes with zeroes)
152 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200153 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200154 *p++ = (data_len >> 24) & 0xff;
155 *p++ = (data_len >> 16) & 0xff;
156 *p++ = (data_len >> 8) & 0xff;
157 *p++ = (data_len)&0xff;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000158 p += 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200159 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200160 memcpy(p, data, data_len);
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000161 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000162
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200163 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000164
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200165 for (i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000166 key[i] = i;
167
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200168 if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, key,
169 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300170 goto exit;
171 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000172
173 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200174 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000175 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200176 for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000177 p = buf;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200178 memset(chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000179 use_len = buf_len;
180
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200181 while (use_len > 0) {
182 for (i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000183 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200184 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200185 use_len -= (use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE) ?
186 MBEDTLS_CTR_DRBG_BLOCKSIZE :
187 use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000188
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200189 if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,
190 chain, chain)) != 0) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300191 goto exit;
192 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000193 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200194
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200195 memcpy(tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000196
197 /*
198 * Update IV
199 */
200 buf[3]++;
201 }
202
203 /*
204 * Do final encryption with reduced data
205 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200206 if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, tmp,
207 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300208 goto exit;
209 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200210 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000211 p = output;
212
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200213 for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
214 if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, iv,
215 iv)) != 0) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300216 goto exit;
217 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200218 memcpy(p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200219 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000220 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300221exit:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200222 mbedtls_aes_free(&aes_ctx);
Dvir Markovich1b364992017-06-26 13:43:34 +0300223 /*
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200224 * tidy up the stack
225 */
226 mbedtls_platform_zeroize(buf, sizeof(buf));
227 mbedtls_platform_zeroize(tmp, sizeof(tmp));
228 mbedtls_platform_zeroize(key, sizeof(key));
229 mbedtls_platform_zeroize(chain, sizeof(chain));
230 if (0 != ret) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300231 /*
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200232 * wipe partial seed from memory
233 */
234 mbedtls_platform_zeroize(output, MBEDTLS_CTR_DRBG_SEEDLEN);
Dvir Markovich1b364992017-06-26 13:43:34 +0300235 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200236
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200237 return ret;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000238}
239
Gilles Peskineed7da592018-08-03 20:16:52 +0200240/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
241 * ctr_drbg_update_internal(ctx, provided_data)
242 * implements
243 * CTR_DRBG_Update(provided_data, Key, V)
244 * with inputs and outputs
245 * ctx->aes_ctx = Key
246 * ctx->counter = V
247 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200248static int
249ctr_drbg_update_internal(mbedtls_ctr_drbg_context *ctx,
250 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN])
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000251{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200252 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000253 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000254 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300255 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000256
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200257 memset(tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000258
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200259 for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000260 /*
261 * Increase counter
262 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200263 for (i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i--)
264 if (++ctx->counter[i - 1] != 0)
Paul Bakker369e14b2012-04-18 14:16:09 +0000265 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000266
267 /*
268 * Crypt counter block
269 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200270 if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
271 ctx->counter, p)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200272 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300273 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000274
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200275 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000276 }
277
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200278 for (i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000279 tmp[i] ^= data[i];
280
281 /*
282 * Update key and counter
283 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200284 if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, tmp,
285 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200286 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300287 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200288 memcpy(ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
289 MBEDTLS_CTR_DRBG_BLOCKSIZE);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000290
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200291exit:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200292 mbedtls_platform_zeroize(tmp, sizeof(tmp));
293 return ret;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000294}
295
Gilles Peskineed7da592018-08-03 20:16:52 +0200296/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
TRodziewicz26371e42021-06-08 16:45:41 +0200297 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
Gilles Peskineed7da592018-08-03 20:16:52 +0200298 * implements
299 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
300 * security_strength) -> initial_working_state
301 * with inputs
302 * ctx->counter = all-bits-0
303 * ctx->aes_ctx = context from all-bits-0 key
304 * additional[:add_len] = entropy_input || nonce || personalization_string
305 * and with outputs
306 * ctx = initial_working_state
307 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200308int mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context *ctx,
309 const unsigned char *additional,
310 size_t add_len)
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000311{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200312 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Janos Follath24eed8d2019-11-22 13:21:35 +0000313 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000314
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200315 if (add_len == 0)
316 return 0;
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100317
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200318 if ((ret = block_cipher_df(add_input, additional, add_len)) != 0)
Gilles Peskined9199932018-09-11 16:41:54 +0200319 goto exit;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200320 if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0)
Gilles Peskined9199932018-09-11 16:41:54 +0200321 goto exit;
322
323exit:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200324 mbedtls_platform_zeroize(add_input, sizeof(add_input));
325 return ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000326}
327
Gilles Peskineed7da592018-08-03 20:16:52 +0200328/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
Gilles Peskine9be50982019-10-22 18:42:27 +0200329 * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
Gilles Peskineed7da592018-08-03 20:16:52 +0200330 * implements
331 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
332 * -> new_working_state
333 * with inputs
334 * ctx contains working_state
335 * additional[:len] = additional_input
336 * and entropy_input comes from calling ctx->f_entropy
Gilles Peskine9be50982019-10-22 18:42:27 +0200337 * for (ctx->entropy_len + nonce_len) bytes
Gilles Peskineed7da592018-08-03 20:16:52 +0200338 * and with output
339 * ctx contains new_working_state
340 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200341static int mbedtls_ctr_drbg_reseed_internal(mbedtls_ctr_drbg_context *ctx,
342 const unsigned char *additional,
343 size_t len,
344 size_t nonce_len)
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000345{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200346 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000347 size_t seedlen = 0;
Janos Follath24eed8d2019-11-22 13:21:35 +0000348 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000349
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200350 if (ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT)
351 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
352 if (nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len)
353 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
354 if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len)
355 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000356
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200357 memset(seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT);
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000358
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200359 /* Gather entropy_len bytes of entropy to seed state. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200360 if (0 != ctx->f_entropy(ctx->p_entropy, seed, ctx->entropy_len)) {
361 return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000362 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000363 seedlen += ctx->entropy_len;
364
Gilles Peskine9be50982019-10-22 18:42:27 +0200365 /* Gather entropy for a nonce if requested. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200366 if (nonce_len != 0) {
367 if (0 != ctx->f_entropy(ctx->p_entropy, seed + seedlen, nonce_len)) {
368 return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
Gilles Peskine9be50982019-10-22 18:42:27 +0200369 }
370 seedlen += nonce_len;
371 }
372
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200373 /* Add additional data if provided. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200374 if (additional != NULL && len != 0) {
375 memcpy(seed + seedlen, additional, len);
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000376 seedlen += len;
377 }
378
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200379 /* Reduce to 384 bits. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200380 if ((ret = block_cipher_df(seed, seed, seedlen)) != 0)
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200381 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000382
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200383 /* Update state. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200384 if ((ret = ctr_drbg_update_internal(ctx, seed)) != 0)
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200385 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000386 ctx->reseed_counter = 1;
387
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200388exit:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200389 mbedtls_platform_zeroize(seed, sizeof(seed));
390 return ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000391}
Paul Bakker9af723c2014-05-01 13:03:14 +0200392
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200393int mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context *ctx,
394 const unsigned char *additional,
395 size_t len)
Gilles Peskine9be50982019-10-22 18:42:27 +0200396{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200397 return mbedtls_ctr_drbg_reseed_internal(ctx, additional, len, 0);
Gilles Peskine9be50982019-10-22 18:42:27 +0200398}
399
Gilles Peskinee9a34542019-10-22 20:43:24 +0200400/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
401 * is sufficient to achieve the maximum security strength given the key
402 * size and entropy length. If there is enough entropy in the initial
403 * call to the entropy function to serve as both the entropy input and
404 * the nonce, don't make a second call to get a nonce. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200405static size_t good_nonce_len(size_t entropy_len)
Gilles Peskinee9a34542019-10-22 20:43:24 +0200406{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200407 if (entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2)
408 return 0;
Gilles Peskinee9a34542019-10-22 20:43:24 +0200409 else
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200410 return (entropy_len + 1) / 2;
Gilles Peskinee9a34542019-10-22 20:43:24 +0200411}
412
Gilles Peskine8bf56132019-10-02 20:31:54 +0200413/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
Gilles Peskine379561f2019-10-18 16:57:48 +0200414 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
Gilles Peskine8bf56132019-10-02 20:31:54 +0200415 * implements
416 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
417 * security_strength) -> initial_working_state
418 * with inputs
419 * custom[:len] = nonce || personalization_string
Gilles Peskine379561f2019-10-18 16:57:48 +0200420 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
Gilles Peskine8bf56132019-10-02 20:31:54 +0200421 * and with outputs
422 * ctx = initial_working_state
423 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200424int mbedtls_ctr_drbg_seed(mbedtls_ctr_drbg_context *ctx,
425 int (*f_entropy)(void *, unsigned char *, size_t),
426 void *p_entropy,
427 const unsigned char *custom,
428 size_t len)
Gilles Peskine8bf56132019-10-02 20:31:54 +0200429{
Janos Follath24eed8d2019-11-22 13:21:35 +0000430 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200431 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Gilles Peskinee9a34542019-10-22 20:43:24 +0200432 size_t nonce_len;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200433
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200434 memset(key, 0, MBEDTLS_CTR_DRBG_KEYSIZE);
Gilles Peskine8bf56132019-10-02 20:31:54 +0200435
Gilles Peskineda290f92021-02-09 18:44:02 +0100436 /* The mutex is initialized iff f_entropy is set. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200437# if defined(MBEDTLS_THREADING_C)
438 mbedtls_mutex_init(&ctx->mutex);
439# endif
Gilles Peskinef4b34292021-01-30 13:05:32 +0100440
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200441 mbedtls_aes_init(&ctx->aes_ctx);
Gilles Peskine8bf56132019-10-02 20:31:54 +0200442
443 ctx->f_entropy = f_entropy;
444 ctx->p_entropy = p_entropy;
445
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200446 if (ctx->entropy_len == 0)
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200447 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskinee9a34542019-10-22 20:43:24 +0200448 /* ctx->reseed_counter contains the desired amount of entropy to
449 * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
450 * If it's -1, indicating that the entropy nonce length was not set
451 * explicitly, use a sufficiently large nonce for security. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200452 nonce_len = (ctx->reseed_counter >= 0 ? (size_t)ctx->reseed_counter :
453 good_nonce_len(ctx->entropy_len));
Gilles Peskinee9a34542019-10-22 20:43:24 +0200454
Gilles Peskine9be50982019-10-22 18:42:27 +0200455 /* Initialize with an empty key. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200456 if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, key,
457 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
458 return ret;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200459 }
460
Gilles Peskinee9a34542019-10-22 20:43:24 +0200461 /* Do the initial seeding. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200462 if ((ret = mbedtls_ctr_drbg_reseed_internal(ctx, custom, len, nonce_len)) !=
463 0) {
464 return ret;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200465 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200466 return 0;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200467}
468
Gilles Peskineed7da592018-08-03 20:16:52 +0200469/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200470 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional,
471 * add_len) implements CTR_DRBG_Reseed(working_state, entropy_input,
472 * additional[:add_len])
Gilles Peskineed7da592018-08-03 20:16:52 +0200473 * -> working_state_after_reseed
474 * if required, then
475 * CTR_DRBG_Generate(working_state_after_reseed,
476 * requested_number_of_bits, additional_input)
477 * -> status, returned_bits, new_working_state
478 * with inputs
479 * ctx contains working_state
480 * requested_number_of_bits = 8 * output_len
481 * additional[:add_len] = additional_input
482 * and entropy_input comes from calling ctx->f_entropy
483 * and with outputs
484 * status = SUCCESS (this function does the reseed internally)
485 * returned_bits = output[:output_len]
486 * ctx contains new_working_state
487 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200488int mbedtls_ctr_drbg_random_with_add(void *p_rng,
489 unsigned char *output,
490 size_t output_len,
491 const unsigned char *additional,
492 size_t add_len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000493{
494 int ret = 0;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200495 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *)p_rng;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200496 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000497 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200498 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000499 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000500 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000501
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200502 if (output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST)
503 return MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000504
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200505 if (add_len > MBEDTLS_CTR_DRBG_MAX_INPUT)
506 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000507
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200508 memset(add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000509
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200510 if (ctx->reseed_counter > ctx->reseed_interval ||
511 ctx->prediction_resistance) {
512 if ((ret = mbedtls_ctr_drbg_reseed(ctx, additional, add_len)) != 0) {
513 return ret;
Dvir Markovich1b364992017-06-26 13:43:34 +0300514 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000515 add_len = 0;
516 }
517
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200518 if (add_len > 0) {
519 if ((ret = block_cipher_df(add_input, additional, add_len)) != 0)
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200520 goto exit;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200521 if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0)
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200522 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000523 }
524
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200525 while (output_len > 0) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000526 /*
527 * Increase counter
528 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200529 for (i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i--)
530 if (++ctx->counter[i - 1] != 0)
Paul Bakker369e14b2012-04-18 14:16:09 +0000531 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000532
533 /*
534 * Crypt counter block
535 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200536 if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
537 ctx->counter, tmp)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200538 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300539 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000540
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200541 use_len = (output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE) ?
542 MBEDTLS_CTR_DRBG_BLOCKSIZE :
543 output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000544 /*
545 * Copy random block to destination
546 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200547 memcpy(p, tmp, use_len);
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000548 p += use_len;
549 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000550 }
551
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200552 if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0)
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200553 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000554
555 ctx->reseed_counter++;
556
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200557exit:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200558 mbedtls_platform_zeroize(add_input, sizeof(add_input));
559 mbedtls_platform_zeroize(tmp, sizeof(tmp));
560 return ret;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000561}
562
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200563int mbedtls_ctr_drbg_random(void *p_rng,
564 unsigned char *output,
565 size_t output_len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000566{
Janos Follath24eed8d2019-11-22 13:21:35 +0000567 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200568 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *)p_rng;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100569
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200570# if defined(MBEDTLS_THREADING_C)
571 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0)
572 return ret;
573# endif
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100574
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200575 ret = mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, NULL, 0);
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100576
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200577# if defined(MBEDTLS_THREADING_C)
578 if (mbedtls_mutex_unlock(&ctx->mutex) != 0)
579 return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
580# endif
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100581
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200582 return ret;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000583}
584
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200585# if defined(MBEDTLS_FS_IO)
586int mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context *ctx,
587 const char *path)
Paul Bakkerfc754a92011-12-05 13:23:51 +0000588{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200589 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000590 FILE *f;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200591 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000592
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200593 if ((f = fopen(path, "wb")) == NULL)
594 return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000595
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200596 if ((ret = mbedtls_ctr_drbg_random(ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT)) !=
597 0)
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200598 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000599
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200600 if (fwrite(buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f) !=
601 MBEDTLS_CTR_DRBG_MAX_INPUT) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200602 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200603 } else {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100604 ret = 0;
Hanno Beckera08651f2018-10-05 09:38:59 +0100605 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000606
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100607exit:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200608 mbedtls_platform_zeroize(buf, sizeof(buf));
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200609
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200610 fclose(f);
611 return ret;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000612}
613
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200614int mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context *ctx,
615 const char *path)
Paul Bakkerfc754a92011-12-05 13:23:51 +0000616{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100617 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200618 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000619 size_t n;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200620 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT];
Gilles Peskine82204662018-09-11 18:43:09 +0200621 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000622
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200623 if ((f = fopen(path, "rb")) == NULL)
624 return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000625
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200626 n = fread(buf, 1, sizeof(buf), f);
627 if (fread(&c, 1, 1, f) != 0) {
Gilles Peskine82204662018-09-11 18:43:09 +0200628 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
629 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100630 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200631 if (n == 0 || ferror(f)) {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100632 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200633 goto exit;
634 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200635 fclose(f);
Gilles Peskine82204662018-09-11 18:43:09 +0200636 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200637
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200638 ret = mbedtls_ctr_drbg_update(ctx, buf, n);
Gilles Peskine82204662018-09-11 18:43:09 +0200639
640exit:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200641 mbedtls_platform_zeroize(buf, sizeof(buf));
642 if (f != NULL)
643 fclose(f);
644 if (ret != 0)
645 return ret;
646 return mbedtls_ctr_drbg_write_seed_file(ctx, path);
Paul Bakkerfc754a92011-12-05 13:23:51 +0000647}
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200648# endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000649
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200650# if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000651
ENT\stroej170f63d02020-12-28 08:50:23 -0600652/* The CTR_DRBG NIST test vectors used here are available at
653 * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip
654 *
655 * The parameters used to derive the test data are:
656 *
657 * [AES-128 use df]
658 * [PredictionResistance = True/False]
659 * [EntropyInputLen = 128]
660 * [NonceLen = 64]
661 * [PersonalizationStringLen = 128]
662 * [AdditionalInputLen = 0]
663 * [ReturnedBitsLen = 512]
664 *
665 * [AES-256 use df]
666 * [PredictionResistance = True/False]
667 * [EntropyInputLen = 256]
668 * [NonceLen = 128]
669 * [PersonalizationStringLen = 256]
670 * [AdditionalInputLen = 0]
671 * [ReturnedBitsLen = 512]
672 *
673 */
674
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200675# if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
676static const unsigned char entropy_source_pr[] = {
677 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb, 0xf1, 0x08, 0x77, 0x2b,
678 0x9e, 0x08, 0xca, 0x92, 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8,
679 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20, 0xec, 0x53, 0xd0, 0x66,
680 0xc3, 0x0f, 0xe3, 0xb0, 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad,
681 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8
682};
Gilles Peskine02e79a42019-10-07 17:06:06 +0200683
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200684static const unsigned char entropy_source_nopr[] = {
685 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45, 0x27, 0x38,
686 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9, 0x74, 0x18, 0x1f, 0x3c,
687 0x22, 0xf6, 0x49, 0x20, 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16,
688 0xb4, 0x6f, 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c
689};
ENT\stroej1df307002020-12-26 12:41:04 -0600690
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200691static const unsigned char pers_pr[] = { 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8,
692 0xb1, 0x7a, 0x9d, 0xfa, 0x45, 0xed,
693 0x21, 0x52, 0xb3, 0xad };
ENT\stroej1df307002020-12-26 12:41:04 -0600694
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200695static const unsigned char pers_nopr[] = { 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72,
696 0xa1, 0x4c, 0xf1, 0x3d, 0xf6, 0x5e,
697 0xa3, 0xa6, 0xe5, 0x0f };
ENT\stroej1df307002020-12-26 12:41:04 -0600698
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200699static const unsigned char result_pr[] = {
700 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66, 0x4f, 0x25, 0x0b,
701 0x2b, 0xde, 0xd8, 0xfa, 0xff, 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41,
702 0x7a, 0x10, 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30, 0xc9,
703 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4, 0x87, 0x42, 0xd5, 0xae,
704 0x5e, 0x5e, 0x43, 0xcc, 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4,
705 0x06, 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf
706};
ENT\stroej1df307002020-12-26 12:41:04 -0600707
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200708static const unsigned char result_nopr[] = {
709 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13, 0x3c, 0xd3, 0x96,
710 0xf9, 0xbc, 0x2c, 0x12, 0xc0, 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09,
711 0x99, 0xaf, 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2, 0x33,
712 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7, 0xa2, 0x53, 0xdc, 0xee,
713 0x18, 0xfc, 0xa7, 0xf2, 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff,
714 0x02, 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8
715};
716# else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000717
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200718static const unsigned char entropy_source_pr[] = {
719 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49, 0xd4, 0xe0, 0x5b, 0xe2,
720 0x39, 0x50, 0xd9, 0x8a, 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85,
721 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e, 0xc5, 0xea, 0x24, 0xc0,
722 0xfa, 0x0c, 0x90, 0x15, 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45,
723 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8, 0x2f, 0x9f, 0xbc, 0x88,
724 0x3f, 0x80, 0xd1, 0x2c, 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3,
725 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce, 0xc8, 0x92, 0x35, 0x55,
726 0x2a, 0xd9, 0x1d, 0x8e, 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76,
727 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77, 0xc0, 0xe7, 0xe6, 0x0c,
728 0x47, 0x44, 0x95, 0xbe
729};
ENT\stroej1df307002020-12-26 12:41:04 -0600730
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200731static const unsigned char entropy_source_nopr[] = {
732 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d, 0x50, 0xc9, 0x22, 0xe4,
733 0x9b, 0x0d, 0xfc, 0xd0, 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73,
734 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c, 0x01, 0x69, 0x62, 0xa7,
735 0xfd, 0x27, 0x87, 0xa2, 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1,
736 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a, 0x1b, 0x01, 0x33, 0xf2,
737 0xc2, 0x38, 0x91, 0xdb, 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a,
738 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7
739};
ENT\stroej1df307002020-12-26 12:41:04 -0600740
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200741static const unsigned char pers_pr[] = {
742 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33, 0x91, 0x53, 0x7e,
743 0x75, 0xd6, 0x19, 0x9d, 0x1e, 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c,
744 0x1f, 0xe0, 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9
745};
ENT\stroej1df307002020-12-26 12:41:04 -0600746
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200747static const unsigned char pers_nopr[] = {
748 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29, 0x4b, 0xda, 0xcd,
749 0x60, 0x99, 0xeb, 0xe4, 0xbf, 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71,
750 0xe5, 0xeb, 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b
751};
ENT\stroej1df307002020-12-26 12:41:04 -0600752
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200753static const unsigned char result_pr[] = {
754 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85, 0x04, 0xc5, 0xc0,
755 0x42, 0xc2, 0x31, 0xc6, 0x1d, 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d,
756 0xcc, 0x62, 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d, 0xa4,
757 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb, 0xdd, 0xe7, 0x02, 0x23,
758 0x63, 0x21, 0xd0, 0x39, 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49,
759 0x40, 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43
760};
ENT\stroej1df307002020-12-26 12:41:04 -0600761
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200762static const unsigned char result_nopr[] = {
763 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad, 0xaf, 0x28, 0xf6,
764 0xb7, 0x95, 0xe9, 0xf1, 0xf3, 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0,
765 0x46, 0x7b, 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14, 0x75,
766 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54, 0xe2, 0xf4, 0x09, 0x66,
767 0xea, 0x33, 0x64, 0x30, 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87,
768 0x3a, 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98
769};
770# endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000771
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100772static size_t test_offset;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200773static int
774ctr_drbg_self_test_entropy(void *data, unsigned char *buf, size_t len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000775{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100776 const unsigned char *p = data;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200777 memcpy(buf, p + test_offset, len);
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100778 test_offset += len;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200779 return 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000780}
781
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200782# define CHK(c) \
783 if ((c) != 0) { \
784 if (verbose != 0) \
785 mbedtls_printf("failed\n"); \
786 return 1; \
787 }
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100788
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200789# define SELF_TEST_OUPUT_DISCARD_LENGTH 64
stroebeljcd4de1b52021-01-04 18:14:32 -0600790
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000791/*
792 * Checkup routine
793 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200794int mbedtls_ctr_drbg_self_test(int verbose)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000795{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200796 mbedtls_ctr_drbg_context ctx;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200797 unsigned char buf[sizeof(result_pr)];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000798
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200799 mbedtls_ctr_drbg_init(&ctx);
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200800
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000801 /*
802 * Based on a NIST CTR_DRBG test vector (PR = True)
803 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200804 if (verbose != 0)
805 mbedtls_printf(" CTR_DRBG (PR = TRUE) : ");
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000806
807 test_offset = 0;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200808 mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
809 mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2);
810 CHK(mbedtls_ctr_drbg_seed(&ctx, ctr_drbg_self_test_entropy,
811 (void *)entropy_source_pr, pers_pr,
812 MBEDTLS_CTR_DRBG_KEYSIZE));
813 mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_ON);
814 CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUPUT_DISCARD_LENGTH));
815 CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_pr)));
816 CHK(memcmp(buf, result_pr, sizeof(result_pr)));
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000817
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200818 mbedtls_ctr_drbg_free(&ctx);
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100819
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200820 if (verbose != 0)
821 mbedtls_printf("passed\n");
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000822
823 /*
824 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
825 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200826 if (verbose != 0)
827 mbedtls_printf(" CTR_DRBG (PR = FALSE): ");
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000828
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200829 mbedtls_ctr_drbg_init(&ctx);
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100830
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000831 test_offset = 0;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200832 mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
833 mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2);
834 CHK(mbedtls_ctr_drbg_seed(&ctx, ctr_drbg_self_test_entropy,
835 (void *)entropy_source_nopr, pers_nopr,
836 MBEDTLS_CTR_DRBG_KEYSIZE));
837 CHK(mbedtls_ctr_drbg_reseed(&ctx, NULL, 0));
838 CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUPUT_DISCARD_LENGTH));
839 CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_nopr)));
840 CHK(memcmp(buf, result_nopr, sizeof(result_nopr)));
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000841
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200842 mbedtls_ctr_drbg_free(&ctx);
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100843
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200844 if (verbose != 0)
845 mbedtls_printf("passed\n");
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000846
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200847 if (verbose != 0)
848 mbedtls_printf("\n");
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000849
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200850 return 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000851}
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200852# endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000853
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200854#endif /* MBEDTLS_CTR_DRBG_C */