blob: 6f553dca662e8698dba4d6b1d6599fc42df7aaec [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 *
Tom Cosgroveaaec1372023-08-04 13:53:36 +010022 * https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-90r.pdf
Paul Bakker0e04d0e2011-11-27 14:46:59 +000023 */
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
Dave Rodgmanf488c2c2023-06-28 11:35:25 +010033#include <limits.h>
Rich Evans00ab4702015-02-06 13:43:58 +000034#include <string.h>
35
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020036#if defined(MBEDTLS_FS_IO)
Paul Bakkerfc754a92011-12-05 13:23:51 +000037#include <stdio.h>
38#endif
39
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000040#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010041
Paul Bakker18d32912011-12-10 21:42:49 +000042/*
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020043 * CTR_DRBG context initialization
44 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010045void mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context *ctx)
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020046{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010047 memset(ctx, 0, sizeof(mbedtls_ctr_drbg_context));
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 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010059void mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context *ctx)
Paul Bakkerfff03662014-06-18 16:21:25 +020060{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010061 if (ctx == NULL) {
Paul Bakkerfff03662014-06-18 16:21:25 +020062 return;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010063 }
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. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010067 if (ctx->f_entropy != NULL) {
68 mbedtls_mutex_free(&ctx->mutex);
69 }
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010070#endif
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010071 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010077void 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010083void 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010089int 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. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010094 if (ctx->f_entropy != NULL) {
95 return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
96 }
Gilles Peskine9be50982019-10-22 18:42:27 +020097
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010098 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. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100105 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;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100115 return 0;
Gilles Peskine9be50982019-10-22 18:42:27 +0200116}
117
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100118void 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100124static 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100139 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100143 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;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100155 MBEDTLS_PUT_UINT32_BE(data_len, p, 0);
Joe Subbiania651e6f2021-08-23 11:35:25 +0100156 p += 4 + 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200157 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100158 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100163 for (i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000164 key[i] = i;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100165 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000166
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100167 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 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100175 for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000176 p = buf;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100177 memset(chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000178 use_len = buf_len;
179
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100180 while (use_len > 0) {
181 for (i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000182 chain[i] ^= p[i];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100183 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200184 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100185 use_len -= (use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE) ?
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200186 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000187
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100188 if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,
189 chain, chain)) != 0) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300190 goto exit;
191 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000192 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200193
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100194 memcpy(tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000195
196 /*
197 * Update IV
198 */
199 buf[3]++;
200 }
201
202 /*
203 * Do final encryption with reduced data
204 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100205 if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, tmp,
206 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300207 goto exit;
208 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200209 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000210 p = output;
211
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100212 for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
213 if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,
214 iv, iv)) != 0) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300215 goto exit;
216 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100217 memcpy(p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200218 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000219 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300220exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100221 mbedtls_aes_free(&aes_ctx);
Dvir Markovich1b364992017-06-26 13:43:34 +0300222 /*
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100223 * tidy up the stack
224 */
225 mbedtls_platform_zeroize(buf, sizeof(buf));
226 mbedtls_platform_zeroize(tmp, sizeof(tmp));
227 mbedtls_platform_zeroize(key, sizeof(key));
228 mbedtls_platform_zeroize(chain, sizeof(chain));
229 if (0 != ret) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300230 /*
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100231 * wipe partial seed from memory
232 */
233 mbedtls_platform_zeroize(output, MBEDTLS_CTR_DRBG_SEEDLEN);
Dvir Markovich1b364992017-06-26 13:43:34 +0300234 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200235
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100236 return ret;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000237}
238
Gilles Peskineed7da592018-08-03 20:16:52 +0200239/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
240 * ctr_drbg_update_internal(ctx, provided_data)
241 * implements
242 * CTR_DRBG_Update(provided_data, Key, V)
243 * with inputs and outputs
244 * ctx->aes_ctx = Key
245 * ctx->counter = V
246 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100247static int ctr_drbg_update_internal(mbedtls_ctr_drbg_context *ctx,
248 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN])
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000249{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200250 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000251 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000252 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300253 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000254
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100255 memset(tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000256
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100257 for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000258 /*
259 * Increase counter
260 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100261 for (i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i--) {
262 if (++ctx->counter[i - 1] != 0) {
Paul Bakker369e14b2012-04-18 14:16:09 +0000263 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100264 }
265 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000266
267 /*
268 * Crypt counter block
269 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100270 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100278 for (i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000279 tmp[i] ^= data[i];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100280 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000281
282 /*
283 * Update key and counter
284 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100285 if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, tmp,
286 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200287 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300288 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100289 memcpy(ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
290 MBEDTLS_CTR_DRBG_BLOCKSIZE);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000291
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200292exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100293 mbedtls_platform_zeroize(tmp, sizeof(tmp));
294 return ret;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000295}
296
Gilles Peskineed7da592018-08-03 20:16:52 +0200297/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
298 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
299 * implements
300 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
301 * security_strength) -> initial_working_state
302 * with inputs
303 * ctx->counter = all-bits-0
304 * ctx->aes_ctx = context from all-bits-0 key
305 * additional[:add_len] = entropy_input || nonce || personalization_string
306 * and with outputs
307 * ctx = initial_working_state
308 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100309int mbedtls_ctr_drbg_update_ret(mbedtls_ctr_drbg_context *ctx,
310 const unsigned char *additional,
311 size_t add_len)
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000312{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200313 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Janos Follath24eed8d2019-11-22 13:21:35 +0000314 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000315
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100316 if (add_len == 0) {
317 return 0;
318 }
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100319
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100320 if ((ret = block_cipher_df(add_input, additional, add_len)) != 0) {
Gilles Peskined9199932018-09-11 16:41:54 +0200321 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100322 }
323 if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {
Gilles Peskined9199932018-09-11 16:41:54 +0200324 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100325 }
Gilles Peskined9199932018-09-11 16:41:54 +0200326
327exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100328 mbedtls_platform_zeroize(add_input, sizeof(add_input));
329 return ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000330}
331
Gilles Peskined9199932018-09-11 16:41:54 +0200332#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100333void mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context *ctx,
334 const unsigned char *additional,
335 size_t add_len)
Gilles Peskined9199932018-09-11 16:41:54 +0200336{
337 /* MAX_INPUT would be more logical here, but we have to match
338 * block_cipher_df()'s limits since we can't propagate errors */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100339 if (add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
Gilles Peskined9199932018-09-11 16:41:54 +0200340 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100341 }
342 (void) mbedtls_ctr_drbg_update_ret(ctx, additional, add_len);
Gilles Peskined9199932018-09-11 16:41:54 +0200343}
344#endif /* MBEDTLS_DEPRECATED_REMOVED */
345
Gilles Peskineed7da592018-08-03 20:16:52 +0200346/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
Gilles Peskine9be50982019-10-22 18:42:27 +0200347 * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
Gilles Peskineed7da592018-08-03 20:16:52 +0200348 * implements
349 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
350 * -> new_working_state
351 * with inputs
352 * ctx contains working_state
353 * additional[:len] = additional_input
354 * and entropy_input comes from calling ctx->f_entropy
Gilles Peskine9be50982019-10-22 18:42:27 +0200355 * for (ctx->entropy_len + nonce_len) bytes
Gilles Peskineed7da592018-08-03 20:16:52 +0200356 * and with output
357 * ctx contains new_working_state
358 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100359static int mbedtls_ctr_drbg_reseed_internal(mbedtls_ctr_drbg_context *ctx,
360 const unsigned char *additional,
361 size_t len,
362 size_t nonce_len)
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000363{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200364 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000365 size_t seedlen = 0;
Janos Follath24eed8d2019-11-22 13:21:35 +0000366 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000367
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100368 if (ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
369 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
370 }
371 if (nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len) {
372 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
373 }
374 if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len) {
375 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
376 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000377
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100378 memset(seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT);
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000379
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200380 /* Gather entropy_len bytes of entropy to seed state. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100381 if (0 != ctx->f_entropy(ctx->p_entropy, seed, ctx->entropy_len)) {
382 return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000383 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000384 seedlen += ctx->entropy_len;
385
Gilles Peskine9be50982019-10-22 18:42:27 +0200386 /* Gather entropy for a nonce if requested. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100387 if (nonce_len != 0) {
388 if (0 != ctx->f_entropy(ctx->p_entropy, seed + seedlen, nonce_len)) {
389 return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
Gilles Peskine9be50982019-10-22 18:42:27 +0200390 }
391 seedlen += nonce_len;
392 }
393
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200394 /* Add additional data if provided. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100395 if (additional != NULL && len != 0) {
396 memcpy(seed + seedlen, additional, len);
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000397 seedlen += len;
398 }
399
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200400 /* Reduce to 384 bits. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100401 if ((ret = block_cipher_df(seed, seed, seedlen)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200402 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100403 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000404
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200405 /* Update state. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100406 if ((ret = ctr_drbg_update_internal(ctx, seed)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200407 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100408 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000409 ctx->reseed_counter = 1;
410
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200411exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100412 mbedtls_platform_zeroize(seed, sizeof(seed));
413 return ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000414}
Paul Bakker9af723c2014-05-01 13:03:14 +0200415
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100416int mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context *ctx,
417 const unsigned char *additional, size_t len)
Gilles Peskine9be50982019-10-22 18:42:27 +0200418{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100419 return mbedtls_ctr_drbg_reseed_internal(ctx, additional, len, 0);
Gilles Peskine9be50982019-10-22 18:42:27 +0200420}
421
Gilles Peskinee9a34542019-10-22 20:43:24 +0200422/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
423 * is sufficient to achieve the maximum security strength given the key
424 * size and entropy length. If there is enough entropy in the initial
425 * call to the entropy function to serve as both the entropy input and
426 * the nonce, don't make a second call to get a nonce. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100427static size_t good_nonce_len(size_t entropy_len)
Gilles Peskinee9a34542019-10-22 20:43:24 +0200428{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100429 if (entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2) {
430 return 0;
431 } else {
432 return (entropy_len + 1) / 2;
433 }
Gilles Peskinee9a34542019-10-22 20:43:24 +0200434}
435
Gilles Peskine8bf56132019-10-02 20:31:54 +0200436/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
Gilles Peskine379561f2019-10-18 16:57:48 +0200437 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
Gilles Peskine8bf56132019-10-02 20:31:54 +0200438 * implements
439 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
440 * security_strength) -> initial_working_state
441 * with inputs
442 * custom[:len] = nonce || personalization_string
Gilles Peskine379561f2019-10-18 16:57:48 +0200443 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
Gilles Peskine8bf56132019-10-02 20:31:54 +0200444 * and with outputs
445 * ctx = initial_working_state
446 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100447int mbedtls_ctr_drbg_seed(mbedtls_ctr_drbg_context *ctx,
448 int (*f_entropy)(void *, unsigned char *, size_t),
449 void *p_entropy,
450 const unsigned char *custom,
451 size_t len)
Gilles Peskine8bf56132019-10-02 20:31:54 +0200452{
Janos Follath24eed8d2019-11-22 13:21:35 +0000453 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200454 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Gilles Peskinee9a34542019-10-22 20:43:24 +0200455 size_t nonce_len;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200456
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100457 memset(key, 0, MBEDTLS_CTR_DRBG_KEYSIZE);
Gilles Peskine8bf56132019-10-02 20:31:54 +0200458
Gilles Peskineda290f92021-02-09 18:44:02 +0100459 /* The mutex is initialized iff f_entropy is set. */
Gilles Peskinef4b34292021-01-30 13:05:32 +0100460#if defined(MBEDTLS_THREADING_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100461 mbedtls_mutex_init(&ctx->mutex);
Gilles Peskinef4b34292021-01-30 13:05:32 +0100462#endif
463
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100464 mbedtls_aes_init(&ctx->aes_ctx);
Gilles Peskine8bf56132019-10-02 20:31:54 +0200465
466 ctx->f_entropy = f_entropy;
467 ctx->p_entropy = p_entropy;
468
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100469 if (ctx->entropy_len == 0) {
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200470 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100471 }
Gilles Peskinee9a34542019-10-22 20:43:24 +0200472 /* ctx->reseed_counter contains the desired amount of entropy to
473 * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
474 * If it's -1, indicating that the entropy nonce length was not set
475 * explicitly, use a sufficiently large nonce for security. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100476 nonce_len = (ctx->reseed_counter >= 0 ?
477 (size_t) ctx->reseed_counter :
478 good_nonce_len(ctx->entropy_len));
Gilles Peskinee9a34542019-10-22 20:43:24 +0200479
Gilles Peskine9be50982019-10-22 18:42:27 +0200480 /* Initialize with an empty key. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100481 if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, key,
482 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
483 return ret;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200484 }
485
Gilles Peskinee9a34542019-10-22 20:43:24 +0200486 /* Do the initial seeding. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100487 if ((ret = mbedtls_ctr_drbg_reseed_internal(ctx, custom, len,
488 nonce_len)) != 0) {
489 return ret;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200490 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100491 return 0;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200492}
493
Gilles Peskineed7da592018-08-03 20:16:52 +0200494/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
495 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
496 * implements
497 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
498 * -> working_state_after_reseed
499 * if required, then
500 * CTR_DRBG_Generate(working_state_after_reseed,
501 * requested_number_of_bits, additional_input)
502 * -> status, returned_bits, new_working_state
503 * with inputs
504 * ctx contains working_state
505 * requested_number_of_bits = 8 * output_len
506 * additional[:add_len] = additional_input
507 * and entropy_input comes from calling ctx->f_entropy
508 * and with outputs
509 * status = SUCCESS (this function does the reseed internally)
510 * returned_bits = output[:output_len]
511 * ctx contains new_working_state
512 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100513int mbedtls_ctr_drbg_random_with_add(void *p_rng,
514 unsigned char *output, size_t output_len,
515 const unsigned char *additional, size_t add_len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000516{
517 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200518 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
519 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000520 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200521 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000522 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000523 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000524
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100525 if (output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST) {
526 return MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG;
527 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000528
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100529 if (add_len > MBEDTLS_CTR_DRBG_MAX_INPUT) {
530 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
531 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000532
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100533 memset(add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000534
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100535 if (ctx->reseed_counter > ctx->reseed_interval ||
536 ctx->prediction_resistance) {
537 if ((ret = mbedtls_ctr_drbg_reseed(ctx, additional, add_len)) != 0) {
538 return ret;
Dvir Markovich1b364992017-06-26 13:43:34 +0300539 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000540 add_len = 0;
541 }
542
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100543 if (add_len > 0) {
544 if ((ret = block_cipher_df(add_input, additional, add_len)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200545 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100546 }
547 if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200548 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100549 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000550 }
551
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100552 while (output_len > 0) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000553 /*
554 * Increase counter
555 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100556 for (i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i--) {
557 if (++ctx->counter[i - 1] != 0) {
Paul Bakker369e14b2012-04-18 14:16:09 +0000558 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100559 }
560 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000561
562 /*
563 * Crypt counter block
564 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100565 if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
566 ctx->counter, tmp)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200567 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300568 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000569
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100570 use_len = (output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE)
Hanno Beckera08651f2018-10-05 09:38:59 +0100571 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000572 /*
573 * Copy random block to destination
574 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100575 memcpy(p, tmp, use_len);
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000576 p += use_len;
577 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000578 }
579
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100580 if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200581 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100582 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000583
584 ctx->reseed_counter++;
585
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200586exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100587 mbedtls_platform_zeroize(add_input, sizeof(add_input));
588 mbedtls_platform_zeroize(tmp, sizeof(tmp));
589 return ret;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000590}
591
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100592int mbedtls_ctr_drbg_random(void *p_rng, unsigned char *output,
593 size_t output_len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000594{
Janos Follath24eed8d2019-11-22 13:21:35 +0000595 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100596 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
597
598#if defined(MBEDTLS_THREADING_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100599 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
600 return ret;
601 }
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100602#endif
603
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100604 ret = mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, NULL, 0);
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100605
606#if defined(MBEDTLS_THREADING_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100607 if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
608 return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
609 }
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100610#endif
611
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100612 return ret;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000613}
614
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200615#if defined(MBEDTLS_FS_IO)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100616int mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context *ctx,
617 const char *path)
Paul Bakkerfc754a92011-12-05 13:23:51 +0000618{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200619 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000620 FILE *f;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100621 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000622
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100623 if ((f = fopen(path, "wb")) == NULL) {
624 return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Hanno Beckera08651f2018-10-05 09:38:59 +0100625 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100626
627 if ((ret = mbedtls_ctr_drbg_random(ctx, buf,
628 MBEDTLS_CTR_DRBG_MAX_INPUT)) != 0) {
629 goto exit;
630 }
631
632 if (fwrite(buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f) !=
633 MBEDTLS_CTR_DRBG_MAX_INPUT) {
634 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
635 } else {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100636 ret = 0;
Hanno Beckera08651f2018-10-05 09:38:59 +0100637 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000638
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100639exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100640 mbedtls_platform_zeroize(buf, sizeof(buf));
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200641
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100642 fclose(f);
643 return ret;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000644}
645
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100646int mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context *ctx,
647 const char *path)
Paul Bakkerfc754a92011-12-05 13:23:51 +0000648{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100649 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200650 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000651 size_t n;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100652 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT];
Gilles Peskine82204662018-09-11 18:43:09 +0200653 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000654
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100655 if ((f = fopen(path, "rb")) == NULL) {
656 return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
657 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000658
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100659 n = fread(buf, 1, sizeof(buf), f);
660 if (fread(&c, 1, 1, f) != 0) {
Gilles Peskine82204662018-09-11 18:43:09 +0200661 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
662 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100663 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100664 if (n == 0 || ferror(f)) {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100665 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200666 goto exit;
667 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100668 fclose(f);
Gilles Peskine82204662018-09-11 18:43:09 +0200669 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200670
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100671 ret = mbedtls_ctr_drbg_update_ret(ctx, buf, n);
Gilles Peskine82204662018-09-11 18:43:09 +0200672
673exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100674 mbedtls_platform_zeroize(buf, sizeof(buf));
675 if (f != NULL) {
676 fclose(f);
677 }
678 if (ret != 0) {
679 return ret;
680 }
681 return mbedtls_ctr_drbg_write_seed_file(ctx, path);
Paul Bakkerfc754a92011-12-05 13:23:51 +0000682}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200683#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000684
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200685#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000686
ENT\stroej170f63d02020-12-28 08:50:23 -0600687/* The CTR_DRBG NIST test vectors used here are available at
688 * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip
689 *
690 * The parameters used to derive the test data are:
691 *
692 * [AES-128 use df]
693 * [PredictionResistance = True/False]
694 * [EntropyInputLen = 128]
695 * [NonceLen = 64]
696 * [PersonalizationStringLen = 128]
697 * [AdditionalInputLen = 0]
698 * [ReturnedBitsLen = 512]
699 *
700 * [AES-256 use df]
701 * [PredictionResistance = True/False]
702 * [EntropyInputLen = 256]
703 * [NonceLen = 128]
704 * [PersonalizationStringLen = 256]
705 * [AdditionalInputLen = 0]
706 * [ReturnedBitsLen = 512]
707 *
708 */
709
Gilles Peskine02e79a42019-10-07 17:06:06 +0200710#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
ENT\stroej1df307002020-12-26 12:41:04 -0600711static const unsigned char entropy_source_pr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100712{ 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb,
713 0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92,
714 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8,
715 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20,
716 0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0,
717 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad,
718 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200719
ENT\stroej1df307002020-12-26 12:41:04 -0600720static const unsigned char entropy_source_nopr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100721{ 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45,
722 0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9,
723 0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20,
724 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f,
725 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c };
ENT\stroej1df307002020-12-26 12:41:04 -0600726
stroebeljcd4de1b52021-01-04 18:14:32 -0600727static const unsigned char pers_pr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100728{ 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a,
729 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad };
ENT\stroej1df307002020-12-26 12:41:04 -0600730
stroebeljcd4de1b52021-01-04 18:14:32 -0600731static const unsigned char pers_nopr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100732{ 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c,
733 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f };
ENT\stroej1df307002020-12-26 12:41:04 -0600734
735static const unsigned char result_pr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100736{ 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66,
737 0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff,
738 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10,
739 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30,
740 0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4,
741 0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc,
742 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06,
743 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf };
ENT\stroej1df307002020-12-26 12:41:04 -0600744
745static const unsigned char result_nopr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100746{ 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13,
747 0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0,
748 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf,
749 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2,
750 0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7,
751 0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2,
752 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02,
753 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200754#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000755
ENT\stroej1df307002020-12-26 12:41:04 -0600756static const unsigned char entropy_source_pr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100757{ 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49,
758 0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a,
759 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85,
760 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e,
761 0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15,
762 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45,
763 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8,
764 0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c,
765 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3,
766 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce,
767 0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e,
768 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76,
769 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77,
770 0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe };
ENT\stroej1df307002020-12-26 12:41:04 -0600771
772static const unsigned char entropy_source_nopr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100773{ 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d,
774 0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0,
775 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73,
776 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c,
777 0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2,
778 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1,
779 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a,
780 0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb,
781 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a,
782 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 };
ENT\stroej1df307002020-12-26 12:41:04 -0600783
stroebeljcd4de1b52021-01-04 18:14:32 -0600784static const unsigned char pers_pr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100785{ 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33,
786 0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e,
787 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0,
788 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 };
ENT\stroej1df307002020-12-26 12:41:04 -0600789
stroebeljcd4de1b52021-01-04 18:14:32 -0600790static const unsigned char pers_nopr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100791{ 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29,
792 0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf,
793 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb,
794 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b };
ENT\stroej1df307002020-12-26 12:41:04 -0600795
796static const unsigned char result_pr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100797{ 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85,
798 0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d,
799 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62,
800 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d,
801 0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb,
802 0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39,
803 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40,
804 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 };
ENT\stroej1df307002020-12-26 12:41:04 -0600805
806static const unsigned char result_nopr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100807{ 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad,
808 0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3,
809 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b,
810 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14,
811 0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54,
812 0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30,
813 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a,
814 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200815#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000816
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100817static size_t test_offset;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100818static int ctr_drbg_self_test_entropy(void *data, unsigned char *buf,
819 size_t len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000820{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100821 const unsigned char *p = data;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100822 memcpy(buf, p + test_offset, len);
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100823 test_offset += len;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100824 return 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000825}
826
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100827#define CHK(c) if ((c) != 0) \
828 { \
829 if (verbose != 0) \
830 mbedtls_printf("failed\n"); \
831 return 1; \
832 }
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100833
bootstrap-prime7ef96ea2022-05-18 14:08:33 -0400834#define SELF_TEST_OUTPUT_DISCARD_LENGTH 64
stroebeljcd4de1b52021-01-04 18:14:32 -0600835
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000836/*
837 * Checkup routine
838 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100839int mbedtls_ctr_drbg_self_test(int verbose)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000840{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200841 mbedtls_ctr_drbg_context ctx;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100842 unsigned char buf[sizeof(result_pr)];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000843
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100844 mbedtls_ctr_drbg_init(&ctx);
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200845
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000846 /*
847 * Based on a NIST CTR_DRBG test vector (PR = True)
848 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100849 if (verbose != 0) {
850 mbedtls_printf(" CTR_DRBG (PR = TRUE) : ");
851 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000852
853 test_offset = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100854 mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
855 mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2);
856 CHK(mbedtls_ctr_drbg_seed(&ctx,
857 ctr_drbg_self_test_entropy,
858 (void *) entropy_source_pr,
859 pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE));
860 mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_ON);
861 CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH));
862 CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_pr)));
863 CHK(memcmp(buf, result_pr, sizeof(result_pr)));
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000864
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100865 mbedtls_ctr_drbg_free(&ctx);
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100866
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100867 if (verbose != 0) {
868 mbedtls_printf("passed\n");
869 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000870
871 /*
872 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
873 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100874 if (verbose != 0) {
875 mbedtls_printf(" CTR_DRBG (PR = FALSE): ");
876 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000877
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100878 mbedtls_ctr_drbg_init(&ctx);
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100879
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000880 test_offset = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100881 mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
882 mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2);
883 CHK(mbedtls_ctr_drbg_seed(&ctx,
884 ctr_drbg_self_test_entropy,
885 (void *) entropy_source_nopr,
886 pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE));
887 CHK(mbedtls_ctr_drbg_reseed(&ctx, NULL, 0));
888 CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH));
889 CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_nopr)));
890 CHK(memcmp(buf, result_nopr, sizeof(result_nopr)));
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000891
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100892 mbedtls_ctr_drbg_free(&ctx);
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100893
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100894 if (verbose != 0) {
895 mbedtls_printf("passed\n");
896 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000897
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100898 if (verbose != 0) {
899 mbedtls_printf("\n");
900 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000901
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100902 return 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000903}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200904#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000905
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200906#endif /* MBEDTLS_CTR_DRBG_C */