blob: 53987a22fff1e4bb5db099b3a7e99a1959356c40 [file] [log] [blame]
Paul Bakker0e04d0e2011-11-27 14:46:59 +00001/*
2 * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Dave Rodgman7ff79652023-11-03 12:04:52 +00005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Paul Bakker0e04d0e2011-11-27 14:46:59 +00006 */
7/*
Paul Sokolovsky8d6d8c82018-02-10 11:11:41 +02008 * The NIST SP 800-90 DRBGs are described in the following publication.
Paul Bakker0e04d0e2011-11-27 14:46:59 +00009 *
Tom Cosgroveaaec1372023-08-04 13:53:36 +010010 * https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-90r.pdf
Paul Bakker0e04d0e2011-11-27 14:46:59 +000011 */
12
Gilles Peskinedb09ef62020-06-03 01:43:33 +020013#include "common.h"
Paul Bakker0e04d0e2011-11-27 14:46:59 +000014
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020015#if defined(MBEDTLS_CTR_DRBG_C)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000016
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000017#include "mbedtls/ctr_drbg.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050018#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000019#include "mbedtls/error.h"
Paul Bakker0e04d0e2011-11-27 14:46:59 +000020
Dave Rodgmanf488c2c2023-06-28 11:35:25 +010021#include <limits.h>
Rich Evans00ab4702015-02-06 13:43:58 +000022#include <string.h>
23
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020024#if defined(MBEDTLS_FS_IO)
Paul Bakkerfc754a92011-12-05 13:23:51 +000025#include <stdio.h>
26#endif
27
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000028#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010029
Paul Bakker18d32912011-12-10 21:42:49 +000030/*
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020031 * CTR_DRBG context initialization
32 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010033void mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context *ctx)
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020034{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010035 memset(ctx, 0, sizeof(mbedtls_ctr_drbg_context));
Gilles Peskinee9a34542019-10-22 20:43:24 +020036 /* Indicate that the entropy nonce length is not set explicitly.
37 * See mbedtls_ctr_drbg_set_nonce_len(). */
38 ctx->reseed_counter = -1;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010039
Gavin Acquroff6aceb512020-03-01 17:06:11 -080040 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020041}
42
Gavin Acquroff6aceb512020-03-01 17:06:11 -080043/*
44 * This function resets CTR_DRBG context to the state immediately
45 * after initial call of mbedtls_ctr_drbg_init().
46 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010047void mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context *ctx)
Paul Bakkerfff03662014-06-18 16:21:25 +020048{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010049 if (ctx == NULL) {
Paul Bakkerfff03662014-06-18 16:21:25 +020050 return;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010051 }
Paul Bakkerfff03662014-06-18 16:21:25 +020052
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010053#if defined(MBEDTLS_THREADING_C)
Gilles Peskineda290f92021-02-09 18:44:02 +010054 /* The mutex is initialized iff f_entropy is set. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010055 if (ctx->f_entropy != NULL) {
56 mbedtls_mutex_free(&ctx->mutex);
57 }
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010058#endif
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010059 mbedtls_aes_free(&ctx->aes_ctx);
60 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ctr_drbg_context));
Gavin Acquroff6aceb512020-03-01 17:06:11 -080061 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
62 ctx->reseed_counter = -1;
Paul Bakkerfff03662014-06-18 16:21:25 +020063}
64
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010065void mbedtls_ctr_drbg_set_prediction_resistance(mbedtls_ctr_drbg_context *ctx,
66 int resistance)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000067{
68 ctx->prediction_resistance = resistance;
69}
70
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010071void mbedtls_ctr_drbg_set_entropy_len(mbedtls_ctr_drbg_context *ctx,
72 size_t len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000073{
74 ctx->entropy_len = len;
75}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +020076
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010077int mbedtls_ctr_drbg_set_nonce_len(mbedtls_ctr_drbg_context *ctx,
78 size_t len)
Gilles Peskine9be50982019-10-22 18:42:27 +020079{
80 /* If mbedtls_ctr_drbg_seed() has already been called, it's
81 * too late. Return the error code that's closest to making sense. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010082 if (ctx->f_entropy != NULL) {
83 return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
84 }
Gilles Peskine9be50982019-10-22 18:42:27 +020085
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010086 if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
87 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
88 }
Gilles Peskine9be50982019-10-22 18:42:27 +020089#if SIZE_MAX > INT_MAX
90 /* This shouldn't be an issue because
91 * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible
92 * configuration, but make sure anyway. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010093 if (len > INT_MAX) {
94 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
95 }
Gilles Peskine9be50982019-10-22 18:42:27 +020096#endif
97
98 /* For backward compatibility with Mbed TLS <= 2.19, store the
99 * entropy nonce length in a field that already exists, but isn't
100 * used until after the initial seeding. */
101 /* Due to the capping of len above, the value fits in an int. */
102 ctx->reseed_counter = (int) len;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100103 return 0;
Gilles Peskine9be50982019-10-22 18:42:27 +0200104}
105
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100106void mbedtls_ctr_drbg_set_reseed_interval(mbedtls_ctr_drbg_context *ctx,
107 int interval)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000108{
109 ctx->reseed_interval = interval;
110}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200111
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100112static int block_cipher_df(unsigned char *output,
113 const unsigned char *data, size_t data_len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000114{
Hanno Beckera08651f2018-10-05 09:38:59 +0100115 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
116 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200117 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
118 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
119 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100120 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200121 mbedtls_aes_context aes_ctx;
Dvir Markovich1b364992017-06-26 13:43:34 +0300122 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000123
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200124 int i, j;
125 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000126
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100127 if (data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
128 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
129 }
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100130
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100131 memset(buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
132 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16);
133 mbedtls_aes_init(&aes_ctx);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000134
135 /*
136 * Construct IV (16 bytes) and S in buffer
137 * IV = Counter (in 32-bits) padded to 16 with zeroes
138 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
139 * data || 0x80
140 * (Total is padded to a multiple of 16-bytes with zeroes)
141 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200142 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100143 MBEDTLS_PUT_UINT32_BE(data_len, p, 0);
Joe Subbiania651e6f2021-08-23 11:35:25 +0100144 p += 4 + 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200145 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100146 memcpy(p, data, data_len);
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000147 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000148
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200149 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000150
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100151 for (i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000152 key[i] = i;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100153 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000154
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100155 if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, key,
156 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300157 goto exit;
158 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000159
160 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200161 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000162 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100163 for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000164 p = buf;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100165 memset(chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000166 use_len = buf_len;
167
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100168 while (use_len > 0) {
169 for (i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000170 chain[i] ^= p[i];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100171 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200172 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100173 use_len -= (use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE) ?
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200174 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000175
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100176 if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,
177 chain, chain)) != 0) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300178 goto exit;
179 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000180 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200181
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100182 memcpy(tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000183
184 /*
185 * Update IV
186 */
187 buf[3]++;
188 }
189
190 /*
191 * Do final encryption with reduced data
192 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100193 if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, tmp,
194 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300195 goto exit;
196 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200197 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000198 p = output;
199
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100200 for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
201 if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,
202 iv, iv)) != 0) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300203 goto exit;
204 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100205 memcpy(p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200206 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000207 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300208exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100209 mbedtls_aes_free(&aes_ctx);
Dvir Markovich1b364992017-06-26 13:43:34 +0300210 /*
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100211 * tidy up the stack
212 */
213 mbedtls_platform_zeroize(buf, sizeof(buf));
214 mbedtls_platform_zeroize(tmp, sizeof(tmp));
215 mbedtls_platform_zeroize(key, sizeof(key));
216 mbedtls_platform_zeroize(chain, sizeof(chain));
217 if (0 != ret) {
Dvir Markovich1b364992017-06-26 13:43:34 +0300218 /*
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100219 * wipe partial seed from memory
220 */
221 mbedtls_platform_zeroize(output, MBEDTLS_CTR_DRBG_SEEDLEN);
Dvir Markovich1b364992017-06-26 13:43:34 +0300222 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200223
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100224 return ret;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000225}
226
Gilles Peskineed7da592018-08-03 20:16:52 +0200227/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
228 * ctr_drbg_update_internal(ctx, provided_data)
229 * implements
230 * CTR_DRBG_Update(provided_data, Key, V)
231 * with inputs and outputs
232 * ctx->aes_ctx = Key
233 * ctx->counter = V
234 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100235static int ctr_drbg_update_internal(mbedtls_ctr_drbg_context *ctx,
236 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN])
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000237{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200238 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000239 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000240 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300241 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000242
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100243 memset(tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000244
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100245 for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000246 /*
247 * Increase counter
248 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100249 for (i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i--) {
250 if (++ctx->counter[i - 1] != 0) {
Paul Bakker369e14b2012-04-18 14:16:09 +0000251 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100252 }
253 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000254
255 /*
256 * Crypt counter block
257 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100258 if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
259 ctx->counter, p)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200260 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300261 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000262
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200263 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000264 }
265
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100266 for (i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000267 tmp[i] ^= data[i];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100268 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000269
270 /*
271 * Update key and counter
272 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100273 if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, tmp,
274 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200275 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300276 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100277 memcpy(ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
278 MBEDTLS_CTR_DRBG_BLOCKSIZE);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000279
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200280exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100281 mbedtls_platform_zeroize(tmp, sizeof(tmp));
282 return ret;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000283}
284
Gilles Peskineed7da592018-08-03 20:16:52 +0200285/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
286 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
287 * implements
288 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
289 * security_strength) -> initial_working_state
290 * with inputs
291 * ctx->counter = all-bits-0
292 * ctx->aes_ctx = context from all-bits-0 key
293 * additional[:add_len] = entropy_input || nonce || personalization_string
294 * and with outputs
295 * ctx = initial_working_state
296 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100297int mbedtls_ctr_drbg_update_ret(mbedtls_ctr_drbg_context *ctx,
298 const unsigned char *additional,
299 size_t add_len)
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000300{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200301 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Janos Follath24eed8d2019-11-22 13:21:35 +0000302 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000303
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100304 if (add_len == 0) {
305 return 0;
306 }
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100307
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100308 if ((ret = block_cipher_df(add_input, additional, add_len)) != 0) {
Gilles Peskined9199932018-09-11 16:41:54 +0200309 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100310 }
311 if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {
Gilles Peskined9199932018-09-11 16:41:54 +0200312 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100313 }
Gilles Peskined9199932018-09-11 16:41:54 +0200314
315exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100316 mbedtls_platform_zeroize(add_input, sizeof(add_input));
317 return ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000318}
319
Gilles Peskined9199932018-09-11 16:41:54 +0200320#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100321void mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context *ctx,
322 const unsigned char *additional,
323 size_t add_len)
Gilles Peskined9199932018-09-11 16:41:54 +0200324{
325 /* MAX_INPUT would be more logical here, but we have to match
326 * block_cipher_df()'s limits since we can't propagate errors */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100327 if (add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
Gilles Peskined9199932018-09-11 16:41:54 +0200328 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100329 }
330 (void) mbedtls_ctr_drbg_update_ret(ctx, additional, add_len);
Gilles Peskined9199932018-09-11 16:41:54 +0200331}
332#endif /* MBEDTLS_DEPRECATED_REMOVED */
333
Gilles Peskineed7da592018-08-03 20:16:52 +0200334/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
Gilles Peskine9be50982019-10-22 18:42:27 +0200335 * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
Gilles Peskineed7da592018-08-03 20:16:52 +0200336 * implements
337 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
338 * -> new_working_state
339 * with inputs
340 * ctx contains working_state
341 * additional[:len] = additional_input
342 * and entropy_input comes from calling ctx->f_entropy
Gilles Peskine9be50982019-10-22 18:42:27 +0200343 * for (ctx->entropy_len + nonce_len) bytes
Gilles Peskineed7da592018-08-03 20:16:52 +0200344 * and with output
345 * ctx contains new_working_state
346 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100347static int mbedtls_ctr_drbg_reseed_internal(mbedtls_ctr_drbg_context *ctx,
348 const unsigned char *additional,
349 size_t len,
350 size_t nonce_len)
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000351{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200352 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000353 size_t seedlen = 0;
Janos Follath24eed8d2019-11-22 13:21:35 +0000354 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000355
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100356 if (ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
357 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
358 }
359 if (nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len) {
360 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
361 }
362 if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len) {
363 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
364 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000365
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100366 memset(seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT);
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000367
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200368 /* Gather entropy_len bytes of entropy to seed state. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100369 if (0 != ctx->f_entropy(ctx->p_entropy, seed, ctx->entropy_len)) {
370 return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000371 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000372 seedlen += ctx->entropy_len;
373
Gilles Peskine9be50982019-10-22 18:42:27 +0200374 /* Gather entropy for a nonce if requested. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100375 if (nonce_len != 0) {
376 if (0 != ctx->f_entropy(ctx->p_entropy, seed + seedlen, nonce_len)) {
377 return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
Gilles Peskine9be50982019-10-22 18:42:27 +0200378 }
379 seedlen += nonce_len;
380 }
381
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200382 /* Add additional data if provided. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100383 if (additional != NULL && len != 0) {
384 memcpy(seed + seedlen, additional, len);
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000385 seedlen += len;
386 }
387
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200388 /* Reduce to 384 bits. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100389 if ((ret = block_cipher_df(seed, seed, seedlen)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200390 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100391 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000392
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200393 /* Update state. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100394 if ((ret = ctr_drbg_update_internal(ctx, seed)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200395 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100396 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000397 ctx->reseed_counter = 1;
398
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200399exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100400 mbedtls_platform_zeroize(seed, sizeof(seed));
401 return ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000402}
Paul Bakker9af723c2014-05-01 13:03:14 +0200403
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100404int mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context *ctx,
405 const unsigned char *additional, size_t len)
Gilles Peskine9be50982019-10-22 18:42:27 +0200406{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100407 return mbedtls_ctr_drbg_reseed_internal(ctx, additional, len, 0);
Gilles Peskine9be50982019-10-22 18:42:27 +0200408}
409
Gilles Peskinee9a34542019-10-22 20:43:24 +0200410/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
411 * is sufficient to achieve the maximum security strength given the key
412 * size and entropy length. If there is enough entropy in the initial
413 * call to the entropy function to serve as both the entropy input and
414 * the nonce, don't make a second call to get a nonce. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100415static size_t good_nonce_len(size_t entropy_len)
Gilles Peskinee9a34542019-10-22 20:43:24 +0200416{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100417 if (entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2) {
418 return 0;
419 } else {
420 return (entropy_len + 1) / 2;
421 }
Gilles Peskinee9a34542019-10-22 20:43:24 +0200422}
423
Gilles Peskine8bf56132019-10-02 20:31:54 +0200424/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
Gilles Peskine379561f2019-10-18 16:57:48 +0200425 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
Gilles Peskine8bf56132019-10-02 20:31:54 +0200426 * implements
427 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
428 * security_strength) -> initial_working_state
429 * with inputs
430 * custom[:len] = nonce || personalization_string
Gilles Peskine379561f2019-10-18 16:57:48 +0200431 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
Gilles Peskine8bf56132019-10-02 20:31:54 +0200432 * and with outputs
433 * ctx = initial_working_state
434 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100435int mbedtls_ctr_drbg_seed(mbedtls_ctr_drbg_context *ctx,
436 int (*f_entropy)(void *, unsigned char *, size_t),
437 void *p_entropy,
438 const unsigned char *custom,
439 size_t len)
Gilles Peskine8bf56132019-10-02 20:31:54 +0200440{
Janos Follath24eed8d2019-11-22 13:21:35 +0000441 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200442 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Gilles Peskinee9a34542019-10-22 20:43:24 +0200443 size_t nonce_len;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200444
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100445 memset(key, 0, MBEDTLS_CTR_DRBG_KEYSIZE);
Gilles Peskine8bf56132019-10-02 20:31:54 +0200446
Gilles Peskineda290f92021-02-09 18:44:02 +0100447 /* The mutex is initialized iff f_entropy is set. */
Gilles Peskinef4b34292021-01-30 13:05:32 +0100448#if defined(MBEDTLS_THREADING_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100449 mbedtls_mutex_init(&ctx->mutex);
Gilles Peskinef4b34292021-01-30 13:05:32 +0100450#endif
451
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100452 mbedtls_aes_init(&ctx->aes_ctx);
Gilles Peskine8bf56132019-10-02 20:31:54 +0200453
454 ctx->f_entropy = f_entropy;
455 ctx->p_entropy = p_entropy;
456
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100457 if (ctx->entropy_len == 0) {
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200458 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100459 }
Gilles Peskinee9a34542019-10-22 20:43:24 +0200460 /* ctx->reseed_counter contains the desired amount of entropy to
461 * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
462 * If it's -1, indicating that the entropy nonce length was not set
463 * explicitly, use a sufficiently large nonce for security. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100464 nonce_len = (ctx->reseed_counter >= 0 ?
465 (size_t) ctx->reseed_counter :
466 good_nonce_len(ctx->entropy_len));
Gilles Peskinee9a34542019-10-22 20:43:24 +0200467
Gilles Peskine9be50982019-10-22 18:42:27 +0200468 /* Initialize with an empty key. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100469 if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, key,
470 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
471 return ret;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200472 }
473
Gilles Peskinee9a34542019-10-22 20:43:24 +0200474 /* Do the initial seeding. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100475 if ((ret = mbedtls_ctr_drbg_reseed_internal(ctx, custom, len,
476 nonce_len)) != 0) {
477 return ret;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200478 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100479 return 0;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200480}
481
Gilles Peskineed7da592018-08-03 20:16:52 +0200482/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
483 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
484 * implements
485 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
486 * -> working_state_after_reseed
487 * if required, then
488 * CTR_DRBG_Generate(working_state_after_reseed,
489 * requested_number_of_bits, additional_input)
490 * -> status, returned_bits, new_working_state
491 * with inputs
492 * ctx contains working_state
493 * requested_number_of_bits = 8 * output_len
494 * additional[:add_len] = additional_input
495 * and entropy_input comes from calling ctx->f_entropy
496 * and with outputs
497 * status = SUCCESS (this function does the reseed internally)
498 * returned_bits = output[:output_len]
499 * ctx contains new_working_state
500 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100501int mbedtls_ctr_drbg_random_with_add(void *p_rng,
502 unsigned char *output, size_t output_len,
503 const unsigned char *additional, size_t add_len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000504{
505 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200506 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
507 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000508 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200509 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000510 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000511 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000512
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100513 if (output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST) {
514 return MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG;
515 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000516
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100517 if (add_len > MBEDTLS_CTR_DRBG_MAX_INPUT) {
518 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
519 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000520
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100521 memset(add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN);
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000522
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100523 if (ctx->reseed_counter > ctx->reseed_interval ||
524 ctx->prediction_resistance) {
525 if ((ret = mbedtls_ctr_drbg_reseed(ctx, additional, add_len)) != 0) {
526 return ret;
Dvir Markovich1b364992017-06-26 13:43:34 +0300527 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000528 add_len = 0;
529 }
530
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100531 if (add_len > 0) {
532 if ((ret = block_cipher_df(add_input, additional, add_len)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200533 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100534 }
535 if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200536 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100537 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000538 }
539
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100540 while (output_len > 0) {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000541 /*
542 * Increase counter
543 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100544 for (i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i--) {
545 if (++ctx->counter[i - 1] != 0) {
Paul Bakker369e14b2012-04-18 14:16:09 +0000546 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100547 }
548 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000549
550 /*
551 * Crypt counter block
552 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100553 if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
554 ctx->counter, tmp)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200555 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300556 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000557
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100558 use_len = (output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE)
Hanno Beckera08651f2018-10-05 09:38:59 +0100559 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000560 /*
561 * Copy random block to destination
562 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100563 memcpy(p, tmp, use_len);
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000564 p += use_len;
565 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000566 }
567
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100568 if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200569 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100570 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000571
572 ctx->reseed_counter++;
573
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200574exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100575 mbedtls_platform_zeroize(add_input, sizeof(add_input));
576 mbedtls_platform_zeroize(tmp, sizeof(tmp));
577 return ret;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000578}
579
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100580int mbedtls_ctr_drbg_random(void *p_rng, unsigned char *output,
581 size_t output_len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000582{
Janos Follath24eed8d2019-11-22 13:21:35 +0000583 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100584 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
585
586#if defined(MBEDTLS_THREADING_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100587 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
588 return ret;
589 }
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100590#endif
591
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100592 ret = mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, NULL, 0);
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100593
594#if defined(MBEDTLS_THREADING_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100595 if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
596 return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
597 }
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100598#endif
599
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100600 return ret;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000601}
602
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200603#if defined(MBEDTLS_FS_IO)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100604int mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context *ctx,
605 const char *path)
Paul Bakkerfc754a92011-12-05 13:23:51 +0000606{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200607 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000608 FILE *f;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100609 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000610
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100611 if ((f = fopen(path, "wb")) == NULL) {
612 return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Hanno Beckera08651f2018-10-05 09:38:59 +0100613 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100614
615 if ((ret = mbedtls_ctr_drbg_random(ctx, buf,
616 MBEDTLS_CTR_DRBG_MAX_INPUT)) != 0) {
617 goto exit;
618 }
619
620 if (fwrite(buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f) !=
621 MBEDTLS_CTR_DRBG_MAX_INPUT) {
622 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
623 } else {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100624 ret = 0;
Hanno Beckera08651f2018-10-05 09:38:59 +0100625 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000626
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100627exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100628 mbedtls_platform_zeroize(buf, sizeof(buf));
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200629
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100630 fclose(f);
631 return ret;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000632}
633
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100634int mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context *ctx,
635 const char *path)
Paul Bakkerfc754a92011-12-05 13:23:51 +0000636{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100637 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200638 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000639 size_t n;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100640 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT];
Gilles Peskine82204662018-09-11 18:43:09 +0200641 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000642
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100643 if ((f = fopen(path, "rb")) == NULL) {
644 return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
645 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000646
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100647 n = fread(buf, 1, sizeof(buf), f);
648 if (fread(&c, 1, 1, f) != 0) {
Gilles Peskine82204662018-09-11 18:43:09 +0200649 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
650 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100651 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100652 if (n == 0 || ferror(f)) {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100653 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200654 goto exit;
655 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100656 fclose(f);
Gilles Peskine82204662018-09-11 18:43:09 +0200657 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200658
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100659 ret = mbedtls_ctr_drbg_update_ret(ctx, buf, n);
Gilles Peskine82204662018-09-11 18:43:09 +0200660
661exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100662 mbedtls_platform_zeroize(buf, sizeof(buf));
663 if (f != NULL) {
664 fclose(f);
665 }
666 if (ret != 0) {
667 return ret;
668 }
669 return mbedtls_ctr_drbg_write_seed_file(ctx, path);
Paul Bakkerfc754a92011-12-05 13:23:51 +0000670}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200671#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000672
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200673#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000674
ENT\stroej170f63d02020-12-28 08:50:23 -0600675/* The CTR_DRBG NIST test vectors used here are available at
676 * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip
677 *
678 * The parameters used to derive the test data are:
679 *
680 * [AES-128 use df]
681 * [PredictionResistance = True/False]
682 * [EntropyInputLen = 128]
683 * [NonceLen = 64]
684 * [PersonalizationStringLen = 128]
685 * [AdditionalInputLen = 0]
686 * [ReturnedBitsLen = 512]
687 *
688 * [AES-256 use df]
689 * [PredictionResistance = True/False]
690 * [EntropyInputLen = 256]
691 * [NonceLen = 128]
692 * [PersonalizationStringLen = 256]
693 * [AdditionalInputLen = 0]
694 * [ReturnedBitsLen = 512]
695 *
696 */
697
Gilles Peskine02e79a42019-10-07 17:06:06 +0200698#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
ENT\stroej1df307002020-12-26 12:41:04 -0600699static const unsigned char entropy_source_pr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100700{ 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb,
701 0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92,
702 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8,
703 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20,
704 0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0,
705 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad,
706 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200707
ENT\stroej1df307002020-12-26 12:41:04 -0600708static const unsigned char entropy_source_nopr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100709{ 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45,
710 0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9,
711 0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20,
712 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f,
713 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c };
ENT\stroej1df307002020-12-26 12:41:04 -0600714
stroebeljcd4de1b52021-01-04 18:14:32 -0600715static const unsigned char pers_pr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100716{ 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a,
717 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad };
ENT\stroej1df307002020-12-26 12:41:04 -0600718
stroebeljcd4de1b52021-01-04 18:14:32 -0600719static const unsigned char pers_nopr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100720{ 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c,
721 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f };
ENT\stroej1df307002020-12-26 12:41:04 -0600722
723static const unsigned char result_pr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100724{ 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66,
725 0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff,
726 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10,
727 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30,
728 0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4,
729 0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc,
730 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06,
731 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf };
ENT\stroej1df307002020-12-26 12:41:04 -0600732
733static const unsigned char result_nopr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100734{ 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13,
735 0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0,
736 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf,
737 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2,
738 0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7,
739 0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2,
740 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02,
741 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200742#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000743
ENT\stroej1df307002020-12-26 12:41:04 -0600744static const unsigned char entropy_source_pr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100745{ 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49,
746 0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a,
747 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85,
748 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e,
749 0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15,
750 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45,
751 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8,
752 0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c,
753 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3,
754 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce,
755 0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e,
756 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76,
757 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77,
758 0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe };
ENT\stroej1df307002020-12-26 12:41:04 -0600759
760static const unsigned char entropy_source_nopr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100761{ 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d,
762 0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0,
763 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73,
764 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c,
765 0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2,
766 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1,
767 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a,
768 0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb,
769 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a,
770 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 };
ENT\stroej1df307002020-12-26 12:41:04 -0600771
stroebeljcd4de1b52021-01-04 18:14:32 -0600772static const unsigned char pers_pr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100773{ 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33,
774 0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e,
775 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0,
776 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 };
ENT\stroej1df307002020-12-26 12:41:04 -0600777
stroebeljcd4de1b52021-01-04 18:14:32 -0600778static const unsigned char pers_nopr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100779{ 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29,
780 0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf,
781 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb,
782 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b };
ENT\stroej1df307002020-12-26 12:41:04 -0600783
784static const unsigned char result_pr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100785{ 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85,
786 0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d,
787 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62,
788 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d,
789 0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb,
790 0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39,
791 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40,
792 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 };
ENT\stroej1df307002020-12-26 12:41:04 -0600793
794static const unsigned char result_nopr[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100795{ 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad,
796 0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3,
797 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b,
798 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14,
799 0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54,
800 0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30,
801 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a,
802 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 };
Gilles Peskine02e79a42019-10-07 17:06:06 +0200803#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000804
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100805static size_t test_offset;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100806static int ctr_drbg_self_test_entropy(void *data, unsigned char *buf,
807 size_t len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000808{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100809 const unsigned char *p = data;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100810 memcpy(buf, p + test_offset, len);
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100811 test_offset += len;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100812 return 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000813}
814
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100815#define CHK(c) if ((c) != 0) \
816 { \
817 if (verbose != 0) \
818 mbedtls_printf("failed\n"); \
819 return 1; \
820 }
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100821
bootstrap-prime7ef96ea2022-05-18 14:08:33 -0400822#define SELF_TEST_OUTPUT_DISCARD_LENGTH 64
stroebeljcd4de1b52021-01-04 18:14:32 -0600823
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000824/*
825 * Checkup routine
826 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100827int mbedtls_ctr_drbg_self_test(int verbose)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000828{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200829 mbedtls_ctr_drbg_context ctx;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100830 unsigned char buf[sizeof(result_pr)];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000831
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100832 mbedtls_ctr_drbg_init(&ctx);
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200833
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000834 /*
835 * Based on a NIST CTR_DRBG test vector (PR = True)
836 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100837 if (verbose != 0) {
838 mbedtls_printf(" CTR_DRBG (PR = TRUE) : ");
839 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000840
841 test_offset = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100842 mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
843 mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2);
844 CHK(mbedtls_ctr_drbg_seed(&ctx,
845 ctr_drbg_self_test_entropy,
846 (void *) entropy_source_pr,
847 pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE));
848 mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_ON);
849 CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH));
850 CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_pr)));
851 CHK(memcmp(buf, result_pr, sizeof(result_pr)));
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000852
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100853 mbedtls_ctr_drbg_free(&ctx);
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100854
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100855 if (verbose != 0) {
856 mbedtls_printf("passed\n");
857 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000858
859 /*
860 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
861 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100862 if (verbose != 0) {
863 mbedtls_printf(" CTR_DRBG (PR = FALSE): ");
864 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000865
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100866 mbedtls_ctr_drbg_init(&ctx);
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100867
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000868 test_offset = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100869 mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
870 mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2);
871 CHK(mbedtls_ctr_drbg_seed(&ctx,
872 ctr_drbg_self_test_entropy,
873 (void *) entropy_source_nopr,
874 pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE));
875 CHK(mbedtls_ctr_drbg_reseed(&ctx, NULL, 0));
876 CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH));
877 CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_nopr)));
878 CHK(memcmp(buf, result_nopr, sizeof(result_nopr)));
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000879
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100880 mbedtls_ctr_drbg_free(&ctx);
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100881
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100882 if (verbose != 0) {
883 mbedtls_printf("passed\n");
884 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000885
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100886 if (verbose != 0) {
887 mbedtls_printf("\n");
888 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000889
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100890 return 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000891}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200892#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000893
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200894#endif /* MBEDTLS_CTR_DRBG_C */