blob: 652c5cbc2806cd84048f749ff9d4722285ec8306 [file] [log] [blame]
Paul Bakker0e04d0e2011-11-27 14:46:59 +00001/*
2 * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakker0e04d0e2011-11-27 14:46:59 +000018 */
19/*
Paul Sokolovsky8d6d8c82018-02-10 11:11:41 +020020 * The NIST SP 800-90 DRBGs are described in the following publication.
Paul Bakker0e04d0e2011-11-27 14:46:59 +000021 *
22 * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
23 */
24
Gilles Peskinedb09ef62020-06-03 01:43:33 +020025#include "common.h"
Paul Bakker0e04d0e2011-11-27 14:46:59 +000026
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020027#if defined(MBEDTLS_CTR_DRBG_C)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000028
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000029#include "mbedtls/ctr_drbg.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050030#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000031#include "mbedtls/error.h"
Paul Bakker0e04d0e2011-11-27 14:46:59 +000032
Rich Evans00ab4702015-02-06 13:43:58 +000033#include <string.h>
34
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020035#if defined(MBEDTLS_FS_IO)
Paul Bakkerfc754a92011-12-05 13:23:51 +000036#include <stdio.h>
37#endif
38
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000039#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010040
Paul Bakker18d32912011-12-10 21:42:49 +000041/*
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020042 * CTR_DRBG context initialization
43 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010044void mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context *ctx)
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020045{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010046 memset(ctx, 0, sizeof(mbedtls_ctr_drbg_context));
Gilles Peskinee9a34542019-10-22 20:43:24 +020047 /* Indicate that the entropy nonce length is not set explicitly.
48 * See mbedtls_ctr_drbg_set_nonce_len(). */
49 ctx->reseed_counter = -1;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010050
Gavin Acquroff6aceb512020-03-01 17:06:11 -080051 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020052}
53
Gavin Acquroff6aceb512020-03-01 17:06:11 -080054/*
55 * This function resets CTR_DRBG context to the state immediately
56 * after initial call of mbedtls_ctr_drbg_init().
57 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010058void mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context *ctx)
Paul Bakkerfff03662014-06-18 16:21:25 +020059{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010060 if (ctx == NULL) {
Paul Bakkerfff03662014-06-18 16:21:25 +020061 return;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010062 }
Paul Bakkerfff03662014-06-18 16:21:25 +020063
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010064#if defined(MBEDTLS_THREADING_C)
Gilles Peskineda290f92021-02-09 18:44:02 +010065 /* The mutex is initialized iff f_entropy is set. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010066 if (ctx->f_entropy != NULL) {
67 mbedtls_mutex_free(&ctx->mutex);
68 }
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010069#endif
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010070 mbedtls_aes_free(&ctx->aes_ctx);
71 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ctr_drbg_context));
Gavin Acquroff6aceb512020-03-01 17:06:11 -080072 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
73 ctx->reseed_counter = -1;
Paul Bakkerfff03662014-06-18 16:21:25 +020074}
75
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010076void mbedtls_ctr_drbg_set_prediction_resistance(mbedtls_ctr_drbg_context *ctx,
77 int resistance)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000078{
79 ctx->prediction_resistance = resistance;
80}
81
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010082void mbedtls_ctr_drbg_set_entropy_len(mbedtls_ctr_drbg_context *ctx,
83 size_t len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000084{
85 ctx->entropy_len = len;
86}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +020087
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010088int mbedtls_ctr_drbg_set_nonce_len(mbedtls_ctr_drbg_context *ctx,
89 size_t len)
Gilles Peskine9be50982019-10-22 18:42:27 +020090{
91 /* If mbedtls_ctr_drbg_seed() has already been called, it's
92 * too late. Return the error code that's closest to making sense. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010093 if (ctx->f_entropy != NULL) {
94 return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
95 }
Gilles Peskine9be50982019-10-22 18:42:27 +020096
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010097 if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
98 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
99 }
Gilles Peskine9be50982019-10-22 18:42:27 +0200100#if SIZE_MAX > INT_MAX
101 /* This shouldn't be an issue because
102 * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible
103 * configuration, but make sure anyway. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100104 if (len > INT_MAX) {
105 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
106 }
Gilles Peskine9be50982019-10-22 18:42:27 +0200107#endif
108
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. */
113 ctx->reseed_counter = (int) len;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100114 return 0;
Gilles Peskine9be50982019-10-22 18:42:27 +0200115}
116
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100117void 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100123static int block_cipher_df(unsigned char *output,
124 const unsigned char *data, size_t data_len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000125{
Hanno Beckera08651f2018-10-05 09:38:59 +0100126 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
127 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200128 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
129 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
130 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100131 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200132 mbedtls_aes_context aes_ctx;
Dvir Markovich1b364992017-06-26 13:43:34 +0300133 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000134
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200135 int i, j;
136 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000137
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100138 if (data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
139 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
140 }
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100141
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100142 memset(buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
143 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;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100154 MBEDTLS_PUT_UINT32_BE(data_len, p, 0);
Joe Subbiania651e6f2021-08-23 11:35:25 +0100155 p += 4 + 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200156 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100157 memcpy(p, data, data_len);
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000158 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000159
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200160 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000161
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100162 for (i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000163 key[i] = i;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100164 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000165
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100166 if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, key,
167 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300168 goto exit;
169 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000170
171 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200172 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000173 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100174 for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000175 p = buf;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100176 memset(chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000177 use_len = buf_len;
178
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100179 while (use_len > 0) {
180 for (i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000181 chain[i] ^= p[i];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100182 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200183 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100184 use_len -= (use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE) ?
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200185 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000186
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100187 if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,
188 chain, chain)) != 0) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300189 goto exit;
190 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000191 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200192
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100193 memcpy(tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000194
195 /*
196 * Update IV
197 */
198 buf[3]++;
199 }
200
201 /*
202 * Do final encryption with reduced data
203 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100204 if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, tmp,
205 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300206 goto exit;
207 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200208 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000209 p = output;
210
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100211 for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
212 if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,
213 iv, iv)) != 0) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300214 goto exit;
215 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100216 memcpy(p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200217 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000218 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300219exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100220 mbedtls_aes_free(&aes_ctx);
Dvir Markovich1b364992017-06-26 13:43:34 +0300221 /*
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100222 * tidy up the stack
223 */
224 mbedtls_platform_zeroize(buf, sizeof(buf));
225 mbedtls_platform_zeroize(tmp, sizeof(tmp));
226 mbedtls_platform_zeroize(key, sizeof(key));
227 mbedtls_platform_zeroize(chain, sizeof(chain));
228 if (0 != ret) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300229 /*
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100230 * wipe partial seed from memory
231 */
232 mbedtls_platform_zeroize(output, MBEDTLS_CTR_DRBG_SEEDLEN);
Dvir Markovich1b364992017-06-26 13:43:34 +0300233 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200234
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100235 return ret;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000236}
237
Gilles Peskineed7da592018-08-03 20:16:52 +0200238/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
239 * ctr_drbg_update_internal(ctx, provided_data)
240 * implements
241 * CTR_DRBG_Update(provided_data, Key, V)
242 * with inputs and outputs
243 * ctx->aes_ctx = Key
244 * ctx->counter = V
245 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100246static int ctr_drbg_update_internal(mbedtls_ctr_drbg_context *ctx,
247 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN])
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000248{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200249 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000250 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000251 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300252 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000253
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100254 memset(tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000255
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100256 for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000257 /*
258 * Increase counter
259 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100260 for (i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i--) {
261 if (++ctx->counter[i - 1] != 0) {
Paul Bakker369e14b2012-04-18 14:16:09 +0000262 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100263 }
264 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000265
266 /*
267 * Crypt counter block
268 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100269 if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
270 ctx->counter, p)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200271 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300272 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000273
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200274 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000275 }
276
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100277 for (i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000278 tmp[i] ^= data[i];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100279 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000280
281 /*
282 * Update key and counter
283 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100284 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 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100288 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:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100292 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)
297 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
298 * 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 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100308int mbedtls_ctr_drbg_update_ret(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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100315 if (add_len == 0) {
316 return 0;
317 }
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100318
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100319 if ((ret = block_cipher_df(add_input, additional, add_len)) != 0) {
Gilles Peskined9199932018-09-11 16:41:54 +0200320 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100321 }
322 if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {
Gilles Peskined9199932018-09-11 16:41:54 +0200323 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100324 }
Gilles Peskined9199932018-09-11 16:41:54 +0200325
326exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100327 mbedtls_platform_zeroize(add_input, sizeof(add_input));
328 return ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000329}
330
Gilles Peskined9199932018-09-11 16:41:54 +0200331#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100332void mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context *ctx,
333 const unsigned char *additional,
334 size_t add_len)
Gilles Peskined9199932018-09-11 16:41:54 +0200335{
336 /* MAX_INPUT would be more logical here, but we have to match
337 * block_cipher_df()'s limits since we can't propagate errors */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100338 if (add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
Gilles Peskined9199932018-09-11 16:41:54 +0200339 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100340 }
341 (void) mbedtls_ctr_drbg_update_ret(ctx, additional, add_len);
Gilles Peskined9199932018-09-11 16:41:54 +0200342}
343#endif /* MBEDTLS_DEPRECATED_REMOVED */
344
Gilles Peskineed7da592018-08-03 20:16:52 +0200345/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
Gilles Peskine9be50982019-10-22 18:42:27 +0200346 * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
Gilles Peskineed7da592018-08-03 20:16:52 +0200347 * implements
348 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
349 * -> new_working_state
350 * with inputs
351 * ctx contains working_state
352 * additional[:len] = additional_input
353 * and entropy_input comes from calling ctx->f_entropy
Gilles Peskine9be50982019-10-22 18:42:27 +0200354 * for (ctx->entropy_len + nonce_len) bytes
Gilles Peskineed7da592018-08-03 20:16:52 +0200355 * and with output
356 * ctx contains new_working_state
357 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100358static int mbedtls_ctr_drbg_reseed_internal(mbedtls_ctr_drbg_context *ctx,
359 const unsigned char *additional,
360 size_t len,
361 size_t nonce_len)
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000362{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200363 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000364 size_t seedlen = 0;
Janos Follath24eed8d2019-11-22 13:21:35 +0000365 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000366
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100367 if (ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
368 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
369 }
370 if (nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len) {
371 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
372 }
373 if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len) {
374 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
375 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000376
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100377 memset(seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT);
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000378
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200379 /* Gather entropy_len bytes of entropy to seed state. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100380 if (0 != ctx->f_entropy(ctx->p_entropy, seed, ctx->entropy_len)) {
381 return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000382 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000383 seedlen += ctx->entropy_len;
384
Gilles Peskine9be50982019-10-22 18:42:27 +0200385 /* Gather entropy for a nonce if requested. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100386 if (nonce_len != 0) {
387 if (0 != ctx->f_entropy(ctx->p_entropy, seed + seedlen, nonce_len)) {
388 return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
Gilles Peskine9be50982019-10-22 18:42:27 +0200389 }
390 seedlen += nonce_len;
391 }
392
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200393 /* Add additional data if provided. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100394 if (additional != NULL && len != 0) {
395 memcpy(seed + seedlen, additional, len);
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000396 seedlen += len;
397 }
398
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200399 /* Reduce to 384 bits. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100400 if ((ret = block_cipher_df(seed, seed, seedlen)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200401 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100402 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000403
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200404 /* Update state. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100405 if ((ret = ctr_drbg_update_internal(ctx, seed)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200406 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100407 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000408 ctx->reseed_counter = 1;
409
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200410exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100411 mbedtls_platform_zeroize(seed, sizeof(seed));
412 return ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000413}
Paul Bakker9af723c2014-05-01 13:03:14 +0200414
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100415int mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context *ctx,
416 const unsigned char *additional, size_t len)
Gilles Peskine9be50982019-10-22 18:42:27 +0200417{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100418 return mbedtls_ctr_drbg_reseed_internal(ctx, additional, len, 0);
Gilles Peskine9be50982019-10-22 18:42:27 +0200419}
420
Gilles Peskinee9a34542019-10-22 20:43:24 +0200421/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
422 * is sufficient to achieve the maximum security strength given the key
423 * size and entropy length. If there is enough entropy in the initial
424 * call to the entropy function to serve as both the entropy input and
425 * the nonce, don't make a second call to get a nonce. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100426static size_t good_nonce_len(size_t entropy_len)
Gilles Peskinee9a34542019-10-22 20:43:24 +0200427{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100428 if (entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2) {
429 return 0;
430 } else {
431 return (entropy_len + 1) / 2;
432 }
Gilles Peskinee9a34542019-10-22 20:43:24 +0200433}
434
Gilles Peskine8bf56132019-10-02 20:31:54 +0200435/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
Gilles Peskine379561f2019-10-18 16:57:48 +0200436 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
Gilles Peskine8bf56132019-10-02 20:31:54 +0200437 * implements
438 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
439 * security_strength) -> initial_working_state
440 * with inputs
441 * custom[:len] = nonce || personalization_string
Gilles Peskine379561f2019-10-18 16:57:48 +0200442 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
Gilles Peskine8bf56132019-10-02 20:31:54 +0200443 * and with outputs
444 * ctx = initial_working_state
445 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100446int mbedtls_ctr_drbg_seed(mbedtls_ctr_drbg_context *ctx,
447 int (*f_entropy)(void *, unsigned char *, size_t),
448 void *p_entropy,
449 const unsigned char *custom,
450 size_t len)
Gilles Peskine8bf56132019-10-02 20:31:54 +0200451{
Janos Follath24eed8d2019-11-22 13:21:35 +0000452 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200453 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Gilles Peskinee9a34542019-10-22 20:43:24 +0200454 size_t nonce_len;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200455
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100456 memset(key, 0, MBEDTLS_CTR_DRBG_KEYSIZE);
Gilles Peskine8bf56132019-10-02 20:31:54 +0200457
Gilles Peskineda290f92021-02-09 18:44:02 +0100458 /* The mutex is initialized iff f_entropy is set. */
Gilles Peskinef4b34292021-01-30 13:05:32 +0100459#if defined(MBEDTLS_THREADING_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100460 mbedtls_mutex_init(&ctx->mutex);
Gilles Peskinef4b34292021-01-30 13:05:32 +0100461#endif
462
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100463 mbedtls_aes_init(&ctx->aes_ctx);
Gilles Peskine8bf56132019-10-02 20:31:54 +0200464
465 ctx->f_entropy = f_entropy;
466 ctx->p_entropy = p_entropy;
467
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100468 if (ctx->entropy_len == 0) {
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200469 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100470 }
Gilles Peskinee9a34542019-10-22 20:43:24 +0200471 /* ctx->reseed_counter contains the desired amount of entropy to
472 * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
473 * If it's -1, indicating that the entropy nonce length was not set
474 * explicitly, use a sufficiently large nonce for security. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100475 nonce_len = (ctx->reseed_counter >= 0 ?
476 (size_t) ctx->reseed_counter :
477 good_nonce_len(ctx->entropy_len));
Gilles Peskinee9a34542019-10-22 20:43:24 +0200478
Gilles Peskine9be50982019-10-22 18:42:27 +0200479 /* Initialize with an empty key. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100480 if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, key,
481 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
482 return ret;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200483 }
484
Gilles Peskinee9a34542019-10-22 20:43:24 +0200485 /* Do the initial seeding. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100486 if ((ret = mbedtls_ctr_drbg_reseed_internal(ctx, custom, len,
487 nonce_len)) != 0) {
488 return ret;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200489 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100490 return 0;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200491}
492
Gilles Peskineed7da592018-08-03 20:16:52 +0200493/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
494 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
495 * implements
496 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
497 * -> working_state_after_reseed
498 * if required, then
499 * CTR_DRBG_Generate(working_state_after_reseed,
500 * requested_number_of_bits, additional_input)
501 * -> status, returned_bits, new_working_state
502 * with inputs
503 * ctx contains working_state
504 * requested_number_of_bits = 8 * output_len
505 * additional[:add_len] = additional_input
506 * and entropy_input comes from calling ctx->f_entropy
507 * and with outputs
508 * status = SUCCESS (this function does the reseed internally)
509 * returned_bits = output[:output_len]
510 * ctx contains new_working_state
511 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100512int mbedtls_ctr_drbg_random_with_add(void *p_rng,
513 unsigned char *output, size_t output_len,
514 const unsigned char *additional, size_t add_len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000515{
516 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200517 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
518 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000519 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200520 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000521 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000522 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000523
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100524 if (output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST) {
525 return MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG;
526 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000527
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100528 if (add_len > MBEDTLS_CTR_DRBG_MAX_INPUT) {
529 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
530 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000531
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100532 memset(add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000533
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100534 if (ctx->reseed_counter > ctx->reseed_interval ||
535 ctx->prediction_resistance) {
536 if ((ret = mbedtls_ctr_drbg_reseed(ctx, additional, add_len)) != 0) {
537 return ret;
Dvir Markovich1b364992017-06-26 13:43:34 +0300538 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000539 add_len = 0;
540 }
541
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100542 if (add_len > 0) {
543 if ((ret = block_cipher_df(add_input, additional, add_len)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200544 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100545 }
546 if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200547 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100548 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000549 }
550
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100551 while (output_len > 0) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000552 /*
553 * Increase counter
554 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100555 for (i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i--) {
556 if (++ctx->counter[i - 1] != 0) {
Paul Bakker369e14b2012-04-18 14:16:09 +0000557 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100558 }
559 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000560
561 /*
562 * Crypt counter block
563 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100564 if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
565 ctx->counter, tmp)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200566 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300567 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000568
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100569 use_len = (output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE)
Hanno Beckera08651f2018-10-05 09:38:59 +0100570 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000571 /*
572 * Copy random block to destination
573 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100574 memcpy(p, tmp, use_len);
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000575 p += use_len;
576 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000577 }
578
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100579 if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200580 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100581 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000582
583 ctx->reseed_counter++;
584
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200585exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100586 mbedtls_platform_zeroize(add_input, sizeof(add_input));
587 mbedtls_platform_zeroize(tmp, sizeof(tmp));
588 return ret;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000589}
590
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100591int mbedtls_ctr_drbg_random(void *p_rng, unsigned char *output,
592 size_t output_len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000593{
Janos Follath24eed8d2019-11-22 13:21:35 +0000594 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100595 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
596
597#if defined(MBEDTLS_THREADING_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100598 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
599 return ret;
600 }
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100601#endif
602
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100603 ret = mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, NULL, 0);
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100604
605#if defined(MBEDTLS_THREADING_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100606 if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
607 return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
608 }
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100609#endif
610
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100611 return ret;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000612}
613
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200614#if defined(MBEDTLS_FS_IO)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100615int mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context *ctx,
616 const char *path)
Paul Bakkerfc754a92011-12-05 13:23:51 +0000617{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200618 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000619 FILE *f;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100620 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000621
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100622 if ((f = fopen(path, "wb")) == NULL) {
623 return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Hanno Beckera08651f2018-10-05 09:38:59 +0100624 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100625
626 if ((ret = mbedtls_ctr_drbg_random(ctx, buf,
627 MBEDTLS_CTR_DRBG_MAX_INPUT)) != 0) {
628 goto exit;
629 }
630
631 if (fwrite(buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f) !=
632 MBEDTLS_CTR_DRBG_MAX_INPUT) {
633 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
634 } else {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100635 ret = 0;
Hanno Beckera08651f2018-10-05 09:38:59 +0100636 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000637
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100638exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100639 mbedtls_platform_zeroize(buf, sizeof(buf));
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200640
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100641 fclose(f);
642 return ret;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000643}
644
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100645int mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context *ctx,
646 const char *path)
Paul Bakkerfc754a92011-12-05 13:23:51 +0000647{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100648 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200649 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000650 size_t n;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100651 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT];
Gilles Peskine82204662018-09-11 18:43:09 +0200652 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000653
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100654 if ((f = fopen(path, "rb")) == NULL) {
655 return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
656 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000657
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100658 n = fread(buf, 1, sizeof(buf), f);
659 if (fread(&c, 1, 1, f) != 0) {
Gilles Peskine82204662018-09-11 18:43:09 +0200660 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
661 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100662 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100663 if (n == 0 || ferror(f)) {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100664 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200665 goto exit;
666 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100667 fclose(f);
Gilles Peskine82204662018-09-11 18:43:09 +0200668 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200669
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100670 ret = mbedtls_ctr_drbg_update_ret(ctx, buf, n);
Gilles Peskine82204662018-09-11 18:43:09 +0200671
672exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100673 mbedtls_platform_zeroize(buf, sizeof(buf));
674 if (f != NULL) {
675 fclose(f);
676 }
677 if (ret != 0) {
678 return ret;
679 }
680 return mbedtls_ctr_drbg_write_seed_file(ctx, path);
Paul Bakkerfc754a92011-12-05 13:23:51 +0000681}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200682#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000683
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200684#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000685
ENT\stroej170f63d02020-12-28 08:50:23 -0600686/* The CTR_DRBG NIST test vectors used here are available at
687 * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip
688 *
689 * The parameters used to derive the test data are:
690 *
691 * [AES-128 use df]
692 * [PredictionResistance = True/False]
693 * [EntropyInputLen = 128]
694 * [NonceLen = 64]
695 * [PersonalizationStringLen = 128]
696 * [AdditionalInputLen = 0]
697 * [ReturnedBitsLen = 512]
698 *
699 * [AES-256 use df]
700 * [PredictionResistance = True/False]
701 * [EntropyInputLen = 256]
702 * [NonceLen = 128]
703 * [PersonalizationStringLen = 256]
704 * [AdditionalInputLen = 0]
705 * [ReturnedBitsLen = 512]
706 *
707 */
708
Gilles Peskine02e79a42019-10-07 17:06:06 +0200709#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
ENT\stroej1df307002020-12-26 12:41:04 -0600710static const unsigned char entropy_source_pr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100711{ 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb,
712 0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92,
713 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8,
714 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20,
715 0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0,
716 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad,
717 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200718
ENT\stroej1df307002020-12-26 12:41:04 -0600719static const unsigned char entropy_source_nopr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100720{ 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45,
721 0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9,
722 0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20,
723 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f,
724 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c };
ENT\stroej1df307002020-12-26 12:41:04 -0600725
stroebeljcd4de1b52021-01-04 18:14:32 -0600726static const unsigned char pers_pr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100727{ 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a,
728 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad };
ENT\stroej1df307002020-12-26 12:41:04 -0600729
stroebeljcd4de1b52021-01-04 18:14:32 -0600730static const unsigned char pers_nopr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100731{ 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c,
732 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f };
ENT\stroej1df307002020-12-26 12:41:04 -0600733
734static const unsigned char result_pr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100735{ 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66,
736 0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff,
737 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10,
738 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30,
739 0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4,
740 0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc,
741 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06,
742 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf };
ENT\stroej1df307002020-12-26 12:41:04 -0600743
744static const unsigned char result_nopr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100745{ 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13,
746 0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0,
747 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf,
748 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2,
749 0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7,
750 0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2,
751 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02,
752 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200753#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000754
ENT\stroej1df307002020-12-26 12:41:04 -0600755static const unsigned char entropy_source_pr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100756{ 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49,
757 0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a,
758 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85,
759 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e,
760 0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15,
761 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45,
762 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8,
763 0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c,
764 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3,
765 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce,
766 0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e,
767 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76,
768 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77,
769 0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe };
ENT\stroej1df307002020-12-26 12:41:04 -0600770
771static const unsigned char entropy_source_nopr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100772{ 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d,
773 0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0,
774 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73,
775 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c,
776 0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2,
777 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1,
778 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a,
779 0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb,
780 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a,
781 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 };
ENT\stroej1df307002020-12-26 12:41:04 -0600782
stroebeljcd4de1b52021-01-04 18:14:32 -0600783static const unsigned char pers_pr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100784{ 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33,
785 0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e,
786 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0,
787 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 };
ENT\stroej1df307002020-12-26 12:41:04 -0600788
stroebeljcd4de1b52021-01-04 18:14:32 -0600789static const unsigned char pers_nopr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100790{ 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29,
791 0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf,
792 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb,
793 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b };
ENT\stroej1df307002020-12-26 12:41:04 -0600794
795static const unsigned char result_pr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100796{ 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85,
797 0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d,
798 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62,
799 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d,
800 0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb,
801 0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39,
802 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40,
803 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 };
ENT\stroej1df307002020-12-26 12:41:04 -0600804
805static const unsigned char result_nopr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100806{ 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad,
807 0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3,
808 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b,
809 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14,
810 0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54,
811 0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30,
812 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a,
813 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200814#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000815
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100816static size_t test_offset;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100817static int ctr_drbg_self_test_entropy(void *data, unsigned char *buf,
818 size_t len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000819{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100820 const unsigned char *p = data;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100821 memcpy(buf, p + test_offset, len);
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100822 test_offset += len;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100823 return 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000824}
825
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100826#define CHK(c) if ((c) != 0) \
827 { \
828 if (verbose != 0) \
829 mbedtls_printf("failed\n"); \
830 return 1; \
831 }
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100832
bootstrap-prime7ef96ea2022-05-18 14:08:33 -0400833#define SELF_TEST_OUTPUT_DISCARD_LENGTH 64
stroebeljcd4de1b52021-01-04 18:14:32 -0600834
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000835/*
836 * Checkup routine
837 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100838int mbedtls_ctr_drbg_self_test(int verbose)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000839{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200840 mbedtls_ctr_drbg_context ctx;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100841 unsigned char buf[sizeof(result_pr)];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000842
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100843 mbedtls_ctr_drbg_init(&ctx);
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200844
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000845 /*
846 * Based on a NIST CTR_DRBG test vector (PR = True)
847 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100848 if (verbose != 0) {
849 mbedtls_printf(" CTR_DRBG (PR = TRUE) : ");
850 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000851
852 test_offset = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100853 mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
854 mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2);
855 CHK(mbedtls_ctr_drbg_seed(&ctx,
856 ctr_drbg_self_test_entropy,
857 (void *) entropy_source_pr,
858 pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE));
859 mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_ON);
860 CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH));
861 CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_pr)));
862 CHK(memcmp(buf, result_pr, sizeof(result_pr)));
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000863
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100864 mbedtls_ctr_drbg_free(&ctx);
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100865
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100866 if (verbose != 0) {
867 mbedtls_printf("passed\n");
868 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000869
870 /*
871 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
872 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100873 if (verbose != 0) {
874 mbedtls_printf(" CTR_DRBG (PR = FALSE): ");
875 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000876
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100877 mbedtls_ctr_drbg_init(&ctx);
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100878
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000879 test_offset = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100880 mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
881 mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2);
882 CHK(mbedtls_ctr_drbg_seed(&ctx,
883 ctr_drbg_self_test_entropy,
884 (void *) entropy_source_nopr,
885 pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE));
886 CHK(mbedtls_ctr_drbg_reseed(&ctx, NULL, 0));
887 CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH));
888 CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_nopr)));
889 CHK(memcmp(buf, result_nopr, sizeof(result_nopr)));
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000890
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100891 mbedtls_ctr_drbg_free(&ctx);
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100892
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100893 if (verbose != 0) {
894 mbedtls_printf("passed\n");
895 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000896
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100897 if (verbose != 0) {
898 mbedtls_printf("\n");
899 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000900
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100901 return 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000902}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200903#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000904
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200905#endif /* MBEDTLS_CTR_DRBG_C */