1817466cbSJens Wiklander /*
2817466cbSJens Wiklander * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
3817466cbSJens Wiklander *
47901324dSJerome Forissier * Copyright The Mbed TLS Contributors
5b0563631STom Van Eyck * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6817466cbSJens Wiklander */
7817466cbSJens Wiklander /*
83d3b0591SJens Wiklander * The NIST SP 800-90 DRBGs are described in the following publication.
9817466cbSJens Wiklander *
10b0563631STom Van Eyck * https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-90r.pdf
11817466cbSJens Wiklander */
12817466cbSJens Wiklander
137901324dSJerome Forissier #include "common.h"
14817466cbSJens Wiklander
15817466cbSJens Wiklander #if defined(MBEDTLS_CTR_DRBG_C)
16817466cbSJens Wiklander
17b0563631STom Van Eyck #include "ctr.h"
18817466cbSJens Wiklander #include "mbedtls/ctr_drbg.h"
193d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
2011fa71b9SJerome Forissier #include "mbedtls/error.h"
21817466cbSJens Wiklander
22817466cbSJens Wiklander #include <string.h>
23817466cbSJens Wiklander
24817466cbSJens Wiklander #if defined(MBEDTLS_FS_IO)
25817466cbSJens Wiklander #include <stdio.h>
26817466cbSJens Wiklander #endif
27817466cbSJens Wiklander
28b0563631STom Van Eyck /* Using error translation functions from PSA to MbedTLS */
29*cb034002SJerome Forissier #if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
30b0563631STom Van Eyck #include "psa_util_internal.h"
31b0563631STom Van Eyck #endif
32b0563631STom Van Eyck
33817466cbSJens Wiklander #include "mbedtls/platform.h"
34817466cbSJens Wiklander
35*cb034002SJerome Forissier #if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
ctr_drbg_setup_psa_context(mbedtls_ctr_drbg_psa_context * psa_ctx,unsigned char * key,size_t key_len)36b0563631STom Van Eyck static psa_status_t ctr_drbg_setup_psa_context(mbedtls_ctr_drbg_psa_context *psa_ctx,
37b0563631STom Van Eyck unsigned char *key, size_t key_len)
38b0563631STom Van Eyck {
39b0563631STom Van Eyck psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
40b0563631STom Van Eyck psa_status_t status;
41b0563631STom Van Eyck
42b0563631STom Van Eyck psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT);
43b0563631STom Van Eyck psa_set_key_algorithm(&key_attr, PSA_ALG_ECB_NO_PADDING);
44b0563631STom Van Eyck psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
45b0563631STom Van Eyck status = psa_import_key(&key_attr, key, key_len, &psa_ctx->key_id);
46b0563631STom Van Eyck if (status != PSA_SUCCESS) {
47b0563631STom Van Eyck goto exit;
48b0563631STom Van Eyck }
49b0563631STom Van Eyck
50b0563631STom Van Eyck status = psa_cipher_encrypt_setup(&psa_ctx->operation, psa_ctx->key_id, PSA_ALG_ECB_NO_PADDING);
51b0563631STom Van Eyck if (status != PSA_SUCCESS) {
52b0563631STom Van Eyck goto exit;
53b0563631STom Van Eyck }
54b0563631STom Van Eyck
55b0563631STom Van Eyck exit:
56b0563631STom Van Eyck psa_reset_key_attributes(&key_attr);
57b0563631STom Van Eyck return status;
58b0563631STom Van Eyck }
59b0563631STom Van Eyck
ctr_drbg_destroy_psa_contex(mbedtls_ctr_drbg_psa_context * psa_ctx)60b0563631STom Van Eyck static void ctr_drbg_destroy_psa_contex(mbedtls_ctr_drbg_psa_context *psa_ctx)
61b0563631STom Van Eyck {
62b0563631STom Van Eyck psa_cipher_abort(&psa_ctx->operation);
63b0563631STom Van Eyck psa_destroy_key(psa_ctx->key_id);
64b0563631STom Van Eyck
65b0563631STom Van Eyck psa_ctx->operation = psa_cipher_operation_init();
66b0563631STom Van Eyck psa_ctx->key_id = MBEDTLS_SVC_KEY_ID_INIT;
67b0563631STom Van Eyck }
68b0563631STom Van Eyck #endif
69b0563631STom Van Eyck
70817466cbSJens Wiklander /*
71817466cbSJens Wiklander * CTR_DRBG context initialization
72817466cbSJens Wiklander */
mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context * ctx)73817466cbSJens Wiklander void mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context *ctx)
74817466cbSJens Wiklander {
75817466cbSJens Wiklander memset(ctx, 0, sizeof(mbedtls_ctr_drbg_context));
76*cb034002SJerome Forissier #if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
77b0563631STom Van Eyck ctx->psa_ctx.key_id = MBEDTLS_SVC_KEY_ID_INIT;
78b0563631STom Van Eyck ctx->psa_ctx.operation = psa_cipher_operation_init();
79*cb034002SJerome Forissier #else
80*cb034002SJerome Forissier mbedtls_aes_init(&ctx->aes_ctx);
81b0563631STom Van Eyck #endif
8211fa71b9SJerome Forissier /* Indicate that the entropy nonce length is not set explicitly.
8311fa71b9SJerome Forissier * See mbedtls_ctr_drbg_set_nonce_len(). */
8411fa71b9SJerome Forissier ctx->reseed_counter = -1;
85817466cbSJens Wiklander
867901324dSJerome Forissier ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
87817466cbSJens Wiklander }
88817466cbSJens Wiklander
897901324dSJerome Forissier /*
907901324dSJerome Forissier * This function resets CTR_DRBG context to the state immediately
917901324dSJerome Forissier * after initial call of mbedtls_ctr_drbg_init().
927901324dSJerome Forissier */
mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context * ctx)93817466cbSJens Wiklander void mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context *ctx)
94817466cbSJens Wiklander {
9532b31808SJens Wiklander if (ctx == NULL) {
96817466cbSJens Wiklander return;
9732b31808SJens Wiklander }
98817466cbSJens Wiklander
99817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C)
1007901324dSJerome Forissier /* The mutex is initialized iff f_entropy is set. */
10132b31808SJens Wiklander if (ctx->f_entropy != NULL) {
102817466cbSJens Wiklander mbedtls_mutex_free(&ctx->mutex);
10332b31808SJens Wiklander }
104817466cbSJens Wiklander #endif
105*cb034002SJerome Forissier #if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
106b0563631STom Van Eyck ctr_drbg_destroy_psa_contex(&ctx->psa_ctx);
107*cb034002SJerome Forissier #else
108*cb034002SJerome Forissier mbedtls_aes_free(&ctx->aes_ctx);
109b0563631STom Van Eyck #endif
1103d3b0591SJens Wiklander mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ctr_drbg_context));
1117901324dSJerome Forissier ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
1127901324dSJerome Forissier ctx->reseed_counter = -1;
113817466cbSJens Wiklander }
114817466cbSJens Wiklander
mbedtls_ctr_drbg_set_prediction_resistance(mbedtls_ctr_drbg_context * ctx,int resistance)11511fa71b9SJerome Forissier void mbedtls_ctr_drbg_set_prediction_resistance(mbedtls_ctr_drbg_context *ctx,
11611fa71b9SJerome Forissier int resistance)
117817466cbSJens Wiklander {
118817466cbSJens Wiklander ctx->prediction_resistance = resistance;
119817466cbSJens Wiklander }
120817466cbSJens Wiklander
mbedtls_ctr_drbg_set_entropy_len(mbedtls_ctr_drbg_context * ctx,size_t len)12111fa71b9SJerome Forissier void mbedtls_ctr_drbg_set_entropy_len(mbedtls_ctr_drbg_context *ctx,
12211fa71b9SJerome Forissier size_t len)
123817466cbSJens Wiklander {
124817466cbSJens Wiklander ctx->entropy_len = len;
125817466cbSJens Wiklander }
126817466cbSJens Wiklander
mbedtls_ctr_drbg_set_nonce_len(mbedtls_ctr_drbg_context * ctx,size_t len)12711fa71b9SJerome Forissier int mbedtls_ctr_drbg_set_nonce_len(mbedtls_ctr_drbg_context *ctx,
12811fa71b9SJerome Forissier size_t len)
12911fa71b9SJerome Forissier {
13011fa71b9SJerome Forissier /* If mbedtls_ctr_drbg_seed() has already been called, it's
13111fa71b9SJerome Forissier * too late. Return the error code that's closest to making sense. */
13232b31808SJens Wiklander if (ctx->f_entropy != NULL) {
13332b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
13432b31808SJens Wiklander }
13511fa71b9SJerome Forissier
13632b31808SJens Wiklander if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
13732b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
13832b31808SJens Wiklander }
13932b31808SJens Wiklander
14011fa71b9SJerome Forissier /* This shouldn't be an issue because
14111fa71b9SJerome Forissier * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible
14211fa71b9SJerome Forissier * configuration, but make sure anyway. */
14332b31808SJens Wiklander if (len > INT_MAX) {
14432b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
14532b31808SJens Wiklander }
14611fa71b9SJerome Forissier
14711fa71b9SJerome Forissier /* For backward compatibility with Mbed TLS <= 2.19, store the
14811fa71b9SJerome Forissier * entropy nonce length in a field that already exists, but isn't
14911fa71b9SJerome Forissier * used until after the initial seeding. */
15011fa71b9SJerome Forissier /* Due to the capping of len above, the value fits in an int. */
15111fa71b9SJerome Forissier ctx->reseed_counter = (int) len;
15232b31808SJens Wiklander return 0;
15311fa71b9SJerome Forissier }
15411fa71b9SJerome Forissier
mbedtls_ctr_drbg_set_reseed_interval(mbedtls_ctr_drbg_context * ctx,int interval)15511fa71b9SJerome Forissier void mbedtls_ctr_drbg_set_reseed_interval(mbedtls_ctr_drbg_context *ctx,
15611fa71b9SJerome Forissier int interval)
157817466cbSJens Wiklander {
158817466cbSJens Wiklander ctx->reseed_interval = interval;
159817466cbSJens Wiklander }
160817466cbSJens Wiklander
block_cipher_df(unsigned char * output,const unsigned char * data,size_t data_len)161817466cbSJens Wiklander static int block_cipher_df(unsigned char *output,
162817466cbSJens Wiklander const unsigned char *data, size_t data_len)
163817466cbSJens Wiklander {
16411fa71b9SJerome Forissier unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
16511fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
166817466cbSJens Wiklander unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
167817466cbSJens Wiklander unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
168817466cbSJens Wiklander unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
169817466cbSJens Wiklander unsigned char *p, *iv;
1703d3b0591SJens Wiklander int ret = 0;
171*cb034002SJerome Forissier #if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
172b0563631STom Van Eyck psa_status_t status;
173b0563631STom Van Eyck size_t tmp_len;
174b0563631STom Van Eyck mbedtls_ctr_drbg_psa_context psa_ctx;
175b0563631STom Van Eyck
176b0563631STom Van Eyck psa_ctx.key_id = MBEDTLS_SVC_KEY_ID_INIT;
177b0563631STom Van Eyck psa_ctx.operation = psa_cipher_operation_init();
178*cb034002SJerome Forissier #else
179*cb034002SJerome Forissier mbedtls_aes_context aes_ctx;
180b0563631STom Van Eyck #endif
181817466cbSJens Wiklander
182817466cbSJens Wiklander int i, j;
183817466cbSJens Wiklander size_t buf_len, use_len;
184817466cbSJens Wiklander
18532b31808SJens Wiklander if (data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
18632b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
18732b31808SJens Wiklander }
188817466cbSJens Wiklander
18911fa71b9SJerome Forissier memset(buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
19011fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_BLOCKSIZE + 16);
191817466cbSJens Wiklander
192817466cbSJens Wiklander /*
193817466cbSJens Wiklander * Construct IV (16 bytes) and S in buffer
194817466cbSJens Wiklander * IV = Counter (in 32-bits) padded to 16 with zeroes
195817466cbSJens Wiklander * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
196817466cbSJens Wiklander * data || 0x80
197817466cbSJens Wiklander * (Total is padded to a multiple of 16-bytes with zeroes)
198817466cbSJens Wiklander */
199817466cbSJens Wiklander p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
200039e02dfSJerome Forissier MBEDTLS_PUT_UINT32_BE(data_len, p, 0);
201039e02dfSJerome Forissier p += 4 + 3;
202817466cbSJens Wiklander *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
203817466cbSJens Wiklander memcpy(p, data, data_len);
204817466cbSJens Wiklander p[data_len] = 0x80;
205817466cbSJens Wiklander
206817466cbSJens Wiklander buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
207817466cbSJens Wiklander
20832b31808SJens Wiklander for (i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++) {
209817466cbSJens Wiklander key[i] = i;
21032b31808SJens Wiklander }
211817466cbSJens Wiklander
212*cb034002SJerome Forissier #if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
213*cb034002SJerome Forissier status = ctr_drbg_setup_psa_context(&psa_ctx, key, sizeof(key));
214*cb034002SJerome Forissier if (status != PSA_SUCCESS) {
215*cb034002SJerome Forissier ret = psa_generic_status_to_mbedtls(status);
216*cb034002SJerome Forissier goto exit;
217*cb034002SJerome Forissier }
218*cb034002SJerome Forissier #else
219b0563631STom Van Eyck mbedtls_aes_init(&aes_ctx);
220b0563631STom Van Eyck
22111fa71b9SJerome Forissier if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, key,
22232b31808SJens Wiklander MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
2233d3b0591SJens Wiklander goto exit;
2243d3b0591SJens Wiklander }
225b0563631STom Van Eyck #endif
226817466cbSJens Wiklander
227817466cbSJens Wiklander /*
228817466cbSJens Wiklander * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
229817466cbSJens Wiklander */
23032b31808SJens Wiklander for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
231817466cbSJens Wiklander p = buf;
232817466cbSJens Wiklander memset(chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE);
233817466cbSJens Wiklander use_len = buf_len;
234817466cbSJens Wiklander
23532b31808SJens Wiklander while (use_len > 0) {
23632b31808SJens Wiklander mbedtls_xor(chain, chain, p, MBEDTLS_CTR_DRBG_BLOCKSIZE);
237817466cbSJens Wiklander p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
238817466cbSJens Wiklander use_len -= (use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE) ?
239817466cbSJens Wiklander MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
240817466cbSJens Wiklander
241*cb034002SJerome Forissier #if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
242b0563631STom Van Eyck status = psa_cipher_update(&psa_ctx.operation, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE,
243b0563631STom Van Eyck chain, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);
244b0563631STom Van Eyck if (status != PSA_SUCCESS) {
245b0563631STom Van Eyck ret = psa_generic_status_to_mbedtls(status);
246b0563631STom Van Eyck goto exit;
247b0563631STom Van Eyck }
248*cb034002SJerome Forissier #else
249*cb034002SJerome Forissier if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,
250*cb034002SJerome Forissier chain, chain)) != 0) {
251*cb034002SJerome Forissier goto exit;
252*cb034002SJerome Forissier }
253b0563631STom Van Eyck #endif
254817466cbSJens Wiklander }
255817466cbSJens Wiklander
256817466cbSJens Wiklander memcpy(tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE);
257817466cbSJens Wiklander
258817466cbSJens Wiklander /*
259817466cbSJens Wiklander * Update IV
260817466cbSJens Wiklander */
261817466cbSJens Wiklander buf[3]++;
262817466cbSJens Wiklander }
263817466cbSJens Wiklander
264817466cbSJens Wiklander /*
265817466cbSJens Wiklander * Do final encryption with reduced data
266817466cbSJens Wiklander */
267*cb034002SJerome Forissier #if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
268b0563631STom Van Eyck ctr_drbg_destroy_psa_contex(&psa_ctx);
269b0563631STom Van Eyck
270b0563631STom Van Eyck status = ctr_drbg_setup_psa_context(&psa_ctx, tmp, MBEDTLS_CTR_DRBG_KEYSIZE);
271b0563631STom Van Eyck if (status != PSA_SUCCESS) {
272b0563631STom Van Eyck ret = psa_generic_status_to_mbedtls(status);
273b0563631STom Van Eyck goto exit;
274b0563631STom Van Eyck }
275*cb034002SJerome Forissier #else
276*cb034002SJerome Forissier if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, tmp,
277*cb034002SJerome Forissier MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
278*cb034002SJerome Forissier goto exit;
279*cb034002SJerome Forissier }
280b0563631STom Van Eyck #endif
281817466cbSJens Wiklander iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
282817466cbSJens Wiklander p = output;
283817466cbSJens Wiklander
28432b31808SJens Wiklander for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
285*cb034002SJerome Forissier #if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
286b0563631STom Van Eyck status = psa_cipher_update(&psa_ctx.operation, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE,
287b0563631STom Van Eyck iv, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);
288b0563631STom Van Eyck if (status != PSA_SUCCESS) {
289b0563631STom Van Eyck ret = psa_generic_status_to_mbedtls(status);
290b0563631STom Van Eyck goto exit;
291b0563631STom Van Eyck }
292*cb034002SJerome Forissier #else
293*cb034002SJerome Forissier if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,
294*cb034002SJerome Forissier iv, iv)) != 0) {
295*cb034002SJerome Forissier goto exit;
296*cb034002SJerome Forissier }
297b0563631STom Van Eyck #endif
298817466cbSJens Wiklander memcpy(p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE);
299817466cbSJens Wiklander p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
300817466cbSJens Wiklander }
3013d3b0591SJens Wiklander exit:
302*cb034002SJerome Forissier #if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
303b0563631STom Van Eyck ctr_drbg_destroy_psa_contex(&psa_ctx);
304*cb034002SJerome Forissier #else
305*cb034002SJerome Forissier mbedtls_aes_free(&aes_ctx);
306b0563631STom Van Eyck #endif
3073d3b0591SJens Wiklander /*
3083d3b0591SJens Wiklander * tidy up the stack
3093d3b0591SJens Wiklander */
3103d3b0591SJens Wiklander mbedtls_platform_zeroize(buf, sizeof(buf));
3113d3b0591SJens Wiklander mbedtls_platform_zeroize(tmp, sizeof(tmp));
3123d3b0591SJens Wiklander mbedtls_platform_zeroize(key, sizeof(key));
3133d3b0591SJens Wiklander mbedtls_platform_zeroize(chain, sizeof(chain));
31432b31808SJens Wiklander if (0 != ret) {
3153d3b0591SJens Wiklander /*
3163d3b0591SJens Wiklander * wipe partial seed from memory
3173d3b0591SJens Wiklander */
3183d3b0591SJens Wiklander mbedtls_platform_zeroize(output, MBEDTLS_CTR_DRBG_SEEDLEN);
319817466cbSJens Wiklander }
320817466cbSJens Wiklander
32132b31808SJens Wiklander return ret;
3223d3b0591SJens Wiklander }
3233d3b0591SJens Wiklander
3243d3b0591SJens Wiklander /* CTR_DRBG_Update (SP 800-90A §10.2.1.2)
3253d3b0591SJens Wiklander * ctr_drbg_update_internal(ctx, provided_data)
3263d3b0591SJens Wiklander * implements
3273d3b0591SJens Wiklander * CTR_DRBG_Update(provided_data, Key, V)
3283d3b0591SJens Wiklander * with inputs and outputs
3293d3b0591SJens Wiklander * ctx->aes_ctx = Key
3303d3b0591SJens Wiklander * ctx->counter = V
3313d3b0591SJens Wiklander */
ctr_drbg_update_internal(mbedtls_ctr_drbg_context * ctx,const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN])332817466cbSJens Wiklander static int ctr_drbg_update_internal(mbedtls_ctr_drbg_context *ctx,
333817466cbSJens Wiklander const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN])
334817466cbSJens Wiklander {
335817466cbSJens Wiklander unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
336817466cbSJens Wiklander unsigned char *p = tmp;
337b0563631STom Van Eyck int j;
3383d3b0591SJens Wiklander int ret = 0;
339*cb034002SJerome Forissier #if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
340b0563631STom Van Eyck psa_status_t status;
341b0563631STom Van Eyck size_t tmp_len;
342b0563631STom Van Eyck #endif
343817466cbSJens Wiklander
344817466cbSJens Wiklander memset(tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN);
345817466cbSJens Wiklander
34632b31808SJens Wiklander for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
347817466cbSJens Wiklander /*
348817466cbSJens Wiklander * Increase counter
349817466cbSJens Wiklander */
350b0563631STom Van Eyck mbedtls_ctr_increment_counter(ctx->counter);
351817466cbSJens Wiklander
352817466cbSJens Wiklander /*
353817466cbSJens Wiklander * Crypt counter block
354817466cbSJens Wiklander */
355*cb034002SJerome Forissier #if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
356b0563631STom Van Eyck status = psa_cipher_update(&ctx->psa_ctx.operation, ctx->counter, sizeof(ctx->counter),
357b0563631STom Van Eyck p, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);
358b0563631STom Van Eyck if (status != PSA_SUCCESS) {
359b0563631STom Van Eyck ret = psa_generic_status_to_mbedtls(status);
360b0563631STom Van Eyck goto exit;
361b0563631STom Van Eyck }
362*cb034002SJerome Forissier #else
363*cb034002SJerome Forissier if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
364*cb034002SJerome Forissier ctx->counter, p)) != 0) {
365*cb034002SJerome Forissier goto exit;
366*cb034002SJerome Forissier }
367b0563631STom Van Eyck #endif
368817466cbSJens Wiklander
369817466cbSJens Wiklander p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
370817466cbSJens Wiklander }
371817466cbSJens Wiklander
372b0563631STom Van Eyck mbedtls_xor(tmp, tmp, data, MBEDTLS_CTR_DRBG_SEEDLEN);
373817466cbSJens Wiklander
374817466cbSJens Wiklander /*
375817466cbSJens Wiklander * Update key and counter
376817466cbSJens Wiklander */
377*cb034002SJerome Forissier #if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
378b0563631STom Van Eyck ctr_drbg_destroy_psa_contex(&ctx->psa_ctx);
379b0563631STom Van Eyck
380b0563631STom Van Eyck status = ctr_drbg_setup_psa_context(&ctx->psa_ctx, tmp, MBEDTLS_CTR_DRBG_KEYSIZE);
381b0563631STom Van Eyck if (status != PSA_SUCCESS) {
382b0563631STom Van Eyck ret = psa_generic_status_to_mbedtls(status);
383b0563631STom Van Eyck goto exit;
384b0563631STom Van Eyck }
385*cb034002SJerome Forissier #else
386*cb034002SJerome Forissier if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, tmp,
387*cb034002SJerome Forissier MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
388*cb034002SJerome Forissier goto exit;
389*cb034002SJerome Forissier }
390b0563631STom Van Eyck #endif
39111fa71b9SJerome Forissier memcpy(ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
39211fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_BLOCKSIZE);
393817466cbSJens Wiklander
3943d3b0591SJens Wiklander exit:
3953d3b0591SJens Wiklander mbedtls_platform_zeroize(tmp, sizeof(tmp));
39632b31808SJens Wiklander return ret;
397817466cbSJens Wiklander }
398817466cbSJens Wiklander
3993d3b0591SJens Wiklander /* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2)
4003d3b0591SJens Wiklander * mbedtls_ctr_drbg_update(ctx, additional, add_len)
4013d3b0591SJens Wiklander * implements
4023d3b0591SJens Wiklander * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
4033d3b0591SJens Wiklander * security_strength) -> initial_working_state
4043d3b0591SJens Wiklander * with inputs
4053d3b0591SJens Wiklander * ctx->counter = all-bits-0
4063d3b0591SJens Wiklander * ctx->aes_ctx = context from all-bits-0 key
4073d3b0591SJens Wiklander * additional[:add_len] = entropy_input || nonce || personalization_string
4083d3b0591SJens Wiklander * and with outputs
4093d3b0591SJens Wiklander * ctx = initial_working_state
4103d3b0591SJens Wiklander */
mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context * ctx,const unsigned char * additional,size_t add_len)41132b31808SJens Wiklander int mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context *ctx,
4123d3b0591SJens Wiklander const unsigned char *additional,
4133d3b0591SJens Wiklander size_t add_len)
414817466cbSJens Wiklander {
415817466cbSJens Wiklander unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
41611fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
417817466cbSJens Wiklander
41832b31808SJens Wiklander if (add_len == 0) {
41932b31808SJens Wiklander return 0;
42032b31808SJens Wiklander }
4213d3b0591SJens Wiklander
42232b31808SJens Wiklander if ((ret = block_cipher_df(add_input, additional, add_len)) != 0) {
4233d3b0591SJens Wiklander goto exit;
42432b31808SJens Wiklander }
42532b31808SJens Wiklander if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {
4263d3b0591SJens Wiklander goto exit;
42732b31808SJens Wiklander }
4283d3b0591SJens Wiklander
4293d3b0591SJens Wiklander exit:
4303d3b0591SJens Wiklander mbedtls_platform_zeroize(add_input, sizeof(add_input));
43132b31808SJens Wiklander return ret;
4323d3b0591SJens Wiklander }
4333d3b0591SJens Wiklander
4343d3b0591SJens Wiklander /* CTR_DRBG_Reseed with derivation function (SP 800-90A §10.2.1.4.2)
43511fa71b9SJerome Forissier * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
4363d3b0591SJens Wiklander * implements
4373d3b0591SJens Wiklander * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
4383d3b0591SJens Wiklander * -> new_working_state
4393d3b0591SJens Wiklander * with inputs
4403d3b0591SJens Wiklander * ctx contains working_state
4413d3b0591SJens Wiklander * additional[:len] = additional_input
4423d3b0591SJens Wiklander * and entropy_input comes from calling ctx->f_entropy
44311fa71b9SJerome Forissier * for (ctx->entropy_len + nonce_len) bytes
4443d3b0591SJens Wiklander * and with output
4453d3b0591SJens Wiklander * ctx contains new_working_state
4463d3b0591SJens Wiklander */
mbedtls_ctr_drbg_reseed_internal(mbedtls_ctr_drbg_context * ctx,const unsigned char * additional,size_t len,size_t nonce_len)44711fa71b9SJerome Forissier static int mbedtls_ctr_drbg_reseed_internal(mbedtls_ctr_drbg_context *ctx,
44811fa71b9SJerome Forissier const unsigned char *additional,
44911fa71b9SJerome Forissier size_t len,
45011fa71b9SJerome Forissier size_t nonce_len)
451817466cbSJens Wiklander {
452817466cbSJens Wiklander unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
453817466cbSJens Wiklander size_t seedlen = 0;
45411fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
455817466cbSJens Wiklander
45632b31808SJens Wiklander if (ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
45732b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
45832b31808SJens Wiklander }
45932b31808SJens Wiklander if (nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len) {
46032b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
46132b31808SJens Wiklander }
46232b31808SJens Wiklander if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len) {
46332b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
46432b31808SJens Wiklander }
465817466cbSJens Wiklander
466817466cbSJens Wiklander memset(seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT);
467817466cbSJens Wiklander
46811fa71b9SJerome Forissier /* Gather entropy_len bytes of entropy to seed state. */
46932b31808SJens Wiklander if (0 != ctx->f_entropy(ctx->p_entropy, seed, ctx->entropy_len)) {
47032b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
471817466cbSJens Wiklander }
472817466cbSJens Wiklander seedlen += ctx->entropy_len;
473817466cbSJens Wiklander
47411fa71b9SJerome Forissier /* Gather entropy for a nonce if requested. */
47532b31808SJens Wiklander if (nonce_len != 0) {
47632b31808SJens Wiklander if (0 != ctx->f_entropy(ctx->p_entropy, seed + seedlen, nonce_len)) {
47732b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
47811fa71b9SJerome Forissier }
47911fa71b9SJerome Forissier seedlen += nonce_len;
48011fa71b9SJerome Forissier }
48111fa71b9SJerome Forissier
48211fa71b9SJerome Forissier /* Add additional data if provided. */
48332b31808SJens Wiklander if (additional != NULL && len != 0) {
484817466cbSJens Wiklander memcpy(seed + seedlen, additional, len);
485817466cbSJens Wiklander seedlen += len;
486817466cbSJens Wiklander }
487817466cbSJens Wiklander
48811fa71b9SJerome Forissier /* Reduce to 384 bits. */
48932b31808SJens Wiklander if ((ret = block_cipher_df(seed, seed, seedlen)) != 0) {
4903d3b0591SJens Wiklander goto exit;
49132b31808SJens Wiklander }
492817466cbSJens Wiklander
49311fa71b9SJerome Forissier /* Update state. */
49432b31808SJens Wiklander if ((ret = ctr_drbg_update_internal(ctx, seed)) != 0) {
4953d3b0591SJens Wiklander goto exit;
49632b31808SJens Wiklander }
497817466cbSJens Wiklander ctx->reseed_counter = 1;
498817466cbSJens Wiklander
4993d3b0591SJens Wiklander exit:
5003d3b0591SJens Wiklander mbedtls_platform_zeroize(seed, sizeof(seed));
50132b31808SJens Wiklander return ret;
502817466cbSJens Wiklander }
503817466cbSJens Wiklander
mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context * ctx,const unsigned char * additional,size_t len)50411fa71b9SJerome Forissier int mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context *ctx,
50511fa71b9SJerome Forissier const unsigned char *additional, size_t len)
50611fa71b9SJerome Forissier {
50732b31808SJens Wiklander return mbedtls_ctr_drbg_reseed_internal(ctx, additional, len, 0);
50811fa71b9SJerome Forissier }
50911fa71b9SJerome Forissier
51011fa71b9SJerome Forissier /* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
51111fa71b9SJerome Forissier * is sufficient to achieve the maximum security strength given the key
51211fa71b9SJerome Forissier * size and entropy length. If there is enough entropy in the initial
51311fa71b9SJerome Forissier * call to the entropy function to serve as both the entropy input and
51411fa71b9SJerome Forissier * the nonce, don't make a second call to get a nonce. */
good_nonce_len(size_t entropy_len)51511fa71b9SJerome Forissier static size_t good_nonce_len(size_t entropy_len)
51611fa71b9SJerome Forissier {
51732b31808SJens Wiklander if (entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2) {
51832b31808SJens Wiklander return 0;
51932b31808SJens Wiklander } else {
52032b31808SJens Wiklander return (entropy_len + 1) / 2;
52132b31808SJens Wiklander }
52211fa71b9SJerome Forissier }
52311fa71b9SJerome Forissier
5245b25c76aSJerome Forissier /* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2)
5255b25c76aSJerome Forissier * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
5265b25c76aSJerome Forissier * implements
5275b25c76aSJerome Forissier * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
5285b25c76aSJerome Forissier * security_strength) -> initial_working_state
5295b25c76aSJerome Forissier * with inputs
5305b25c76aSJerome Forissier * custom[:len] = nonce || personalization_string
5315b25c76aSJerome Forissier * where entropy_input comes from f_entropy for ctx->entropy_len bytes
5325b25c76aSJerome Forissier * and with outputs
5335b25c76aSJerome Forissier * ctx = initial_working_state
5345b25c76aSJerome Forissier */
mbedtls_ctr_drbg_seed(mbedtls_ctr_drbg_context * ctx,int (* f_entropy)(void *,unsigned char *,size_t),void * p_entropy,const unsigned char * custom,size_t len)5355b25c76aSJerome Forissier int mbedtls_ctr_drbg_seed(mbedtls_ctr_drbg_context *ctx,
5365b25c76aSJerome Forissier int (*f_entropy)(void *, unsigned char *, size_t),
5375b25c76aSJerome Forissier void *p_entropy,
5385b25c76aSJerome Forissier const unsigned char *custom,
5395b25c76aSJerome Forissier size_t len)
5405b25c76aSJerome Forissier {
54111fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
5425b25c76aSJerome Forissier unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
54311fa71b9SJerome Forissier size_t nonce_len;
5445b25c76aSJerome Forissier
5455b25c76aSJerome Forissier memset(key, 0, MBEDTLS_CTR_DRBG_KEYSIZE);
5465b25c76aSJerome Forissier
5477901324dSJerome Forissier /* The mutex is initialized iff f_entropy is set. */
5487901324dSJerome Forissier #if defined(MBEDTLS_THREADING_C)
5497901324dSJerome Forissier mbedtls_mutex_init(&ctx->mutex);
5507901324dSJerome Forissier #endif
5517901324dSJerome Forissier
5525b25c76aSJerome Forissier ctx->f_entropy = f_entropy;
5535b25c76aSJerome Forissier ctx->p_entropy = p_entropy;
5545b25c76aSJerome Forissier
55532b31808SJens Wiklander if (ctx->entropy_len == 0) {
5565b25c76aSJerome Forissier ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
55732b31808SJens Wiklander }
55811fa71b9SJerome Forissier /* ctx->reseed_counter contains the desired amount of entropy to
55911fa71b9SJerome Forissier * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
56011fa71b9SJerome Forissier * If it's -1, indicating that the entropy nonce length was not set
56111fa71b9SJerome Forissier * explicitly, use a sufficiently large nonce for security. */
56211fa71b9SJerome Forissier nonce_len = (ctx->reseed_counter >= 0 ?
56311fa71b9SJerome Forissier (size_t) ctx->reseed_counter :
56411fa71b9SJerome Forissier good_nonce_len(ctx->entropy_len));
56511fa71b9SJerome Forissier
56611fa71b9SJerome Forissier /* Initialize with an empty key. */
567*cb034002SJerome Forissier #if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
568b0563631STom Van Eyck psa_status_t status;
569b0563631STom Van Eyck
570b0563631STom Van Eyck status = ctr_drbg_setup_psa_context(&ctx->psa_ctx, key, MBEDTLS_CTR_DRBG_KEYSIZE);
571b0563631STom Van Eyck if (status != PSA_SUCCESS) {
572b0563631STom Van Eyck ret = psa_generic_status_to_mbedtls(status);
573b0563631STom Van Eyck return status;
574b0563631STom Van Eyck }
575*cb034002SJerome Forissier #else
576*cb034002SJerome Forissier if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, key,
577*cb034002SJerome Forissier MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
578*cb034002SJerome Forissier return ret;
579*cb034002SJerome Forissier }
580b0563631STom Van Eyck #endif
5815b25c76aSJerome Forissier
58211fa71b9SJerome Forissier /* Do the initial seeding. */
58311fa71b9SJerome Forissier if ((ret = mbedtls_ctr_drbg_reseed_internal(ctx, custom, len,
58432b31808SJens Wiklander nonce_len)) != 0) {
58532b31808SJens Wiklander return ret;
5865b25c76aSJerome Forissier }
58732b31808SJens Wiklander return 0;
5885b25c76aSJerome Forissier }
5895b25c76aSJerome Forissier
5903d3b0591SJens Wiklander /* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2)
5913d3b0591SJens Wiklander * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
5923d3b0591SJens Wiklander * implements
5933d3b0591SJens Wiklander * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
5943d3b0591SJens Wiklander * -> working_state_after_reseed
5953d3b0591SJens Wiklander * if required, then
5963d3b0591SJens Wiklander * CTR_DRBG_Generate(working_state_after_reseed,
5973d3b0591SJens Wiklander * requested_number_of_bits, additional_input)
5983d3b0591SJens Wiklander * -> status, returned_bits, new_working_state
5993d3b0591SJens Wiklander * with inputs
6003d3b0591SJens Wiklander * ctx contains working_state
6013d3b0591SJens Wiklander * requested_number_of_bits = 8 * output_len
6023d3b0591SJens Wiklander * additional[:add_len] = additional_input
6033d3b0591SJens Wiklander * and entropy_input comes from calling ctx->f_entropy
6043d3b0591SJens Wiklander * and with outputs
6053d3b0591SJens Wiklander * status = SUCCESS (this function does the reseed internally)
6063d3b0591SJens Wiklander * returned_bits = output[:output_len]
6073d3b0591SJens Wiklander * ctx contains new_working_state
6083d3b0591SJens Wiklander */
mbedtls_ctr_drbg_random_with_add(void * p_rng,unsigned char * output,size_t output_len,const unsigned char * additional,size_t add_len)609817466cbSJens Wiklander int mbedtls_ctr_drbg_random_with_add(void *p_rng,
610817466cbSJens Wiklander unsigned char *output, size_t output_len,
611817466cbSJens Wiklander const unsigned char *additional, size_t add_len)
612817466cbSJens Wiklander {
613817466cbSJens Wiklander int ret = 0;
614817466cbSJens Wiklander mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
615817466cbSJens Wiklander unsigned char *p = output;
616b0563631STom Van Eyck struct {
617b0563631STom Van Eyck unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
618817466cbSJens Wiklander unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
619b0563631STom Van Eyck } locals;
620817466cbSJens Wiklander size_t use_len;
621817466cbSJens Wiklander
62232b31808SJens Wiklander if (output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST) {
62332b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG;
62432b31808SJens Wiklander }
625817466cbSJens Wiklander
62632b31808SJens Wiklander if (add_len > MBEDTLS_CTR_DRBG_MAX_INPUT) {
62732b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
62832b31808SJens Wiklander }
629817466cbSJens Wiklander
630b0563631STom Van Eyck memset(locals.add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN);
631817466cbSJens Wiklander
632817466cbSJens Wiklander if (ctx->reseed_counter > ctx->reseed_interval ||
63332b31808SJens Wiklander ctx->prediction_resistance) {
63432b31808SJens Wiklander if ((ret = mbedtls_ctr_drbg_reseed(ctx, additional, add_len)) != 0) {
63532b31808SJens Wiklander return ret;
6363d3b0591SJens Wiklander }
637817466cbSJens Wiklander add_len = 0;
638817466cbSJens Wiklander }
639817466cbSJens Wiklander
64032b31808SJens Wiklander if (add_len > 0) {
641b0563631STom Van Eyck if ((ret = block_cipher_df(locals.add_input, additional, add_len)) != 0) {
6423d3b0591SJens Wiklander goto exit;
643817466cbSJens Wiklander }
644b0563631STom Van Eyck if ((ret = ctr_drbg_update_internal(ctx, locals.add_input)) != 0) {
64532b31808SJens Wiklander goto exit;
64632b31808SJens Wiklander }
64732b31808SJens Wiklander }
648817466cbSJens Wiklander
64932b31808SJens Wiklander while (output_len > 0) {
650817466cbSJens Wiklander /*
651b0563631STom Van Eyck * Increase counter (treat it as a 128-bit big-endian integer).
652817466cbSJens Wiklander */
653b0563631STom Van Eyck mbedtls_ctr_increment_counter(ctx->counter);
654817466cbSJens Wiklander
655817466cbSJens Wiklander /*
656817466cbSJens Wiklander * Crypt counter block
657817466cbSJens Wiklander */
658*cb034002SJerome Forissier #if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
659b0563631STom Van Eyck psa_status_t status;
660b0563631STom Van Eyck size_t tmp_len;
661b0563631STom Van Eyck
662b0563631STom Van Eyck status = psa_cipher_update(&ctx->psa_ctx.operation, ctx->counter, sizeof(ctx->counter),
663b0563631STom Van Eyck locals.tmp, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);
664b0563631STom Van Eyck if (status != PSA_SUCCESS) {
665b0563631STom Van Eyck ret = psa_generic_status_to_mbedtls(status);
666b0563631STom Van Eyck goto exit;
667b0563631STom Van Eyck }
668*cb034002SJerome Forissier #else
669*cb034002SJerome Forissier if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
670*cb034002SJerome Forissier ctx->counter, locals.tmp)) != 0) {
671*cb034002SJerome Forissier goto exit;
672*cb034002SJerome Forissier }
673b0563631STom Van Eyck #endif
674817466cbSJens Wiklander
67511fa71b9SJerome Forissier use_len = (output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE)
67611fa71b9SJerome Forissier ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
677817466cbSJens Wiklander /*
678817466cbSJens Wiklander * Copy random block to destination
679817466cbSJens Wiklander */
680b0563631STom Van Eyck memcpy(p, locals.tmp, use_len);
681817466cbSJens Wiklander p += use_len;
682817466cbSJens Wiklander output_len -= use_len;
683817466cbSJens Wiklander }
684817466cbSJens Wiklander
685b0563631STom Van Eyck if ((ret = ctr_drbg_update_internal(ctx, locals.add_input)) != 0) {
6863d3b0591SJens Wiklander goto exit;
68732b31808SJens Wiklander }
688817466cbSJens Wiklander
689817466cbSJens Wiklander ctx->reseed_counter++;
690817466cbSJens Wiklander
6913d3b0591SJens Wiklander exit:
692b0563631STom Van Eyck mbedtls_platform_zeroize(&locals, sizeof(locals));
69332b31808SJens Wiklander return ret;
694817466cbSJens Wiklander }
695817466cbSJens Wiklander
mbedtls_ctr_drbg_random(void * p_rng,unsigned char * output,size_t output_len)69611fa71b9SJerome Forissier int mbedtls_ctr_drbg_random(void *p_rng, unsigned char *output,
69711fa71b9SJerome Forissier size_t output_len)
698817466cbSJens Wiklander {
69911fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
700817466cbSJens Wiklander mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
701817466cbSJens Wiklander
702817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C)
70332b31808SJens Wiklander if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
70432b31808SJens Wiklander return ret;
70532b31808SJens Wiklander }
706817466cbSJens Wiklander #endif
707817466cbSJens Wiklander
708817466cbSJens Wiklander ret = mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, NULL, 0);
709817466cbSJens Wiklander
710817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C)
71132b31808SJens Wiklander if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
71232b31808SJens Wiklander return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
71332b31808SJens Wiklander }
714817466cbSJens Wiklander #endif
715817466cbSJens Wiklander
71632b31808SJens Wiklander return ret;
717817466cbSJens Wiklander }
718817466cbSJens Wiklander
719817466cbSJens Wiklander #if defined(MBEDTLS_FS_IO)
mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context * ctx,const char * path)72011fa71b9SJerome Forissier int mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context *ctx,
72111fa71b9SJerome Forissier const char *path)
722817466cbSJens Wiklander {
723817466cbSJens Wiklander int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
724817466cbSJens Wiklander FILE *f;
725817466cbSJens Wiklander unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT];
726817466cbSJens Wiklander
72732b31808SJens Wiklander if ((f = fopen(path, "wb")) == NULL) {
72832b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
72932b31808SJens Wiklander }
73032b31808SJens Wiklander
73132b31808SJens Wiklander /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
73232b31808SJens Wiklander mbedtls_setbuf(f, NULL);
733817466cbSJens Wiklander
73411fa71b9SJerome Forissier if ((ret = mbedtls_ctr_drbg_random(ctx, buf,
73532b31808SJens Wiklander MBEDTLS_CTR_DRBG_MAX_INPUT)) != 0) {
736817466cbSJens Wiklander goto exit;
73732b31808SJens Wiklander }
738817466cbSJens Wiklander
73911fa71b9SJerome Forissier if (fwrite(buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f) !=
74032b31808SJens Wiklander MBEDTLS_CTR_DRBG_MAX_INPUT) {
741817466cbSJens Wiklander ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
74232b31808SJens Wiklander } else {
743817466cbSJens Wiklander ret = 0;
74411fa71b9SJerome Forissier }
745817466cbSJens Wiklander
746817466cbSJens Wiklander exit:
7473d3b0591SJens Wiklander mbedtls_platform_zeroize(buf, sizeof(buf));
7483d3b0591SJens Wiklander
749817466cbSJens Wiklander fclose(f);
75032b31808SJens Wiklander return ret;
751817466cbSJens Wiklander }
752817466cbSJens Wiklander
mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context * ctx,const char * path)75311fa71b9SJerome Forissier int mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context *ctx,
75411fa71b9SJerome Forissier const char *path)
755817466cbSJens Wiklander {
7563d3b0591SJens Wiklander int ret = 0;
7573d3b0591SJens Wiklander FILE *f = NULL;
758817466cbSJens Wiklander size_t n;
759817466cbSJens Wiklander unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT];
7603d3b0591SJens Wiklander unsigned char c;
761817466cbSJens Wiklander
76232b31808SJens Wiklander if ((f = fopen(path, "rb")) == NULL) {
76332b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
76432b31808SJens Wiklander }
76532b31808SJens Wiklander
76632b31808SJens Wiklander /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
76732b31808SJens Wiklander mbedtls_setbuf(f, NULL);
768817466cbSJens Wiklander
7693d3b0591SJens Wiklander n = fread(buf, 1, sizeof(buf), f);
77032b31808SJens Wiklander if (fread(&c, 1, 1, f) != 0) {
7713d3b0591SJens Wiklander ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
7723d3b0591SJens Wiklander goto exit;
773817466cbSJens Wiklander }
77432b31808SJens Wiklander if (n == 0 || ferror(f)) {
7753d3b0591SJens Wiklander ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
7763d3b0591SJens Wiklander goto exit;
777817466cbSJens Wiklander }
778817466cbSJens Wiklander fclose(f);
7793d3b0591SJens Wiklander f = NULL;
780817466cbSJens Wiklander
78132b31808SJens Wiklander ret = mbedtls_ctr_drbg_update(ctx, buf, n);
782817466cbSJens Wiklander
7833d3b0591SJens Wiklander exit:
7843d3b0591SJens Wiklander mbedtls_platform_zeroize(buf, sizeof(buf));
78532b31808SJens Wiklander if (f != NULL) {
7863d3b0591SJens Wiklander fclose(f);
78732b31808SJens Wiklander }
78832b31808SJens Wiklander if (ret != 0) {
78932b31808SJens Wiklander return ret;
79032b31808SJens Wiklander }
79132b31808SJens Wiklander return mbedtls_ctr_drbg_write_seed_file(ctx, path);
792817466cbSJens Wiklander }
793817466cbSJens Wiklander #endif /* MBEDTLS_FS_IO */
794817466cbSJens Wiklander
795817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST)
796817466cbSJens Wiklander
7977901324dSJerome Forissier /* The CTR_DRBG NIST test vectors used here are available at
7987901324dSJerome Forissier * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip
7997901324dSJerome Forissier *
8007901324dSJerome Forissier * The parameters used to derive the test data are:
8017901324dSJerome Forissier *
8027901324dSJerome Forissier * [AES-128 use df]
8037901324dSJerome Forissier * [PredictionResistance = True/False]
8047901324dSJerome Forissier * [EntropyInputLen = 128]
8057901324dSJerome Forissier * [NonceLen = 64]
8067901324dSJerome Forissier * [PersonalizationStringLen = 128]
8077901324dSJerome Forissier * [AdditionalInputLen = 0]
8087901324dSJerome Forissier * [ReturnedBitsLen = 512]
8097901324dSJerome Forissier *
8107901324dSJerome Forissier * [AES-256 use df]
8117901324dSJerome Forissier * [PredictionResistance = True/False]
8127901324dSJerome Forissier * [EntropyInputLen = 256]
8137901324dSJerome Forissier * [NonceLen = 128]
8147901324dSJerome Forissier * [PersonalizationStringLen = 256]
8157901324dSJerome Forissier * [AdditionalInputLen = 0]
8167901324dSJerome Forissier * [ReturnedBitsLen = 512]
8177901324dSJerome Forissier *
8187901324dSJerome Forissier */
819817466cbSJens Wiklander
82011fa71b9SJerome Forissier #if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
8217901324dSJerome Forissier static const unsigned char entropy_source_pr[] =
8227901324dSJerome Forissier { 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb,
8237901324dSJerome Forissier 0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92,
8247901324dSJerome Forissier 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8,
8257901324dSJerome Forissier 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20,
8267901324dSJerome Forissier 0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0,
8277901324dSJerome Forissier 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad,
8287901324dSJerome Forissier 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 };
82911fa71b9SJerome Forissier
8307901324dSJerome Forissier static const unsigned char entropy_source_nopr[] =
8317901324dSJerome Forissier { 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45,
8327901324dSJerome Forissier 0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9,
8337901324dSJerome Forissier 0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20,
8347901324dSJerome Forissier 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f,
8357901324dSJerome Forissier 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c };
8367901324dSJerome Forissier
8377901324dSJerome Forissier static const unsigned char pers_pr[] =
8387901324dSJerome Forissier { 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a,
8397901324dSJerome Forissier 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad };
8407901324dSJerome Forissier
8417901324dSJerome Forissier static const unsigned char pers_nopr[] =
8427901324dSJerome Forissier { 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c,
8437901324dSJerome Forissier 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f };
8447901324dSJerome Forissier
8457901324dSJerome Forissier static const unsigned char result_pr[] =
8467901324dSJerome Forissier { 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66,
8477901324dSJerome Forissier 0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff,
8487901324dSJerome Forissier 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10,
8497901324dSJerome Forissier 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30,
8507901324dSJerome Forissier 0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4,
8517901324dSJerome Forissier 0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc,
8527901324dSJerome Forissier 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06,
8537901324dSJerome Forissier 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf };
8547901324dSJerome Forissier
8557901324dSJerome Forissier static const unsigned char result_nopr[] =
8567901324dSJerome Forissier { 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13,
8577901324dSJerome Forissier 0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0,
8587901324dSJerome Forissier 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf,
8597901324dSJerome Forissier 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2,
8607901324dSJerome Forissier 0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7,
8617901324dSJerome Forissier 0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2,
8627901324dSJerome Forissier 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02,
8637901324dSJerome Forissier 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 };
86411fa71b9SJerome Forissier #else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
865817466cbSJens Wiklander
8667901324dSJerome Forissier static const unsigned char entropy_source_pr[] =
8677901324dSJerome Forissier { 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49,
8687901324dSJerome Forissier 0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a,
8697901324dSJerome Forissier 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85,
8707901324dSJerome Forissier 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e,
8717901324dSJerome Forissier 0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15,
8727901324dSJerome Forissier 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45,
8737901324dSJerome Forissier 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8,
8747901324dSJerome Forissier 0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c,
8757901324dSJerome Forissier 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3,
8767901324dSJerome Forissier 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce,
8777901324dSJerome Forissier 0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e,
8787901324dSJerome Forissier 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76,
8797901324dSJerome Forissier 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77,
8807901324dSJerome Forissier 0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe };
8817901324dSJerome Forissier
8827901324dSJerome Forissier static const unsigned char entropy_source_nopr[] =
8837901324dSJerome Forissier { 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d,
8847901324dSJerome Forissier 0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0,
8857901324dSJerome Forissier 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73,
8867901324dSJerome Forissier 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c,
8877901324dSJerome Forissier 0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2,
8887901324dSJerome Forissier 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1,
8897901324dSJerome Forissier 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a,
8907901324dSJerome Forissier 0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb,
8917901324dSJerome Forissier 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a,
8927901324dSJerome Forissier 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 };
8937901324dSJerome Forissier
8947901324dSJerome Forissier static const unsigned char pers_pr[] =
8957901324dSJerome Forissier { 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33,
8967901324dSJerome Forissier 0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e,
8977901324dSJerome Forissier 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0,
8987901324dSJerome Forissier 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 };
8997901324dSJerome Forissier
9007901324dSJerome Forissier static const unsigned char pers_nopr[] =
9017901324dSJerome Forissier { 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29,
9027901324dSJerome Forissier 0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf,
9037901324dSJerome Forissier 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb,
9047901324dSJerome Forissier 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b };
9057901324dSJerome Forissier
9067901324dSJerome Forissier static const unsigned char result_pr[] =
9077901324dSJerome Forissier { 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85,
9087901324dSJerome Forissier 0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d,
9097901324dSJerome Forissier 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62,
9107901324dSJerome Forissier 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d,
9117901324dSJerome Forissier 0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb,
9127901324dSJerome Forissier 0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39,
9137901324dSJerome Forissier 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40,
9147901324dSJerome Forissier 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 };
9157901324dSJerome Forissier
9167901324dSJerome Forissier static const unsigned char result_nopr[] =
9177901324dSJerome Forissier { 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad,
9187901324dSJerome Forissier 0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3,
9197901324dSJerome Forissier 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b,
9207901324dSJerome Forissier 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14,
9217901324dSJerome Forissier 0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54,
9227901324dSJerome Forissier 0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30,
9237901324dSJerome Forissier 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a,
9247901324dSJerome Forissier 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 };
92511fa71b9SJerome Forissier #endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
926817466cbSJens Wiklander
927817466cbSJens Wiklander static size_t test_offset;
ctr_drbg_self_test_entropy(void * data,unsigned char * buf,size_t len)928817466cbSJens Wiklander static int ctr_drbg_self_test_entropy(void *data, unsigned char *buf,
929817466cbSJens Wiklander size_t len)
930817466cbSJens Wiklander {
931817466cbSJens Wiklander const unsigned char *p = data;
932817466cbSJens Wiklander memcpy(buf, p + test_offset, len);
933817466cbSJens Wiklander test_offset += len;
93432b31808SJens Wiklander return 0;
935817466cbSJens Wiklander }
936817466cbSJens Wiklander
937817466cbSJens Wiklander #define CHK(c) if ((c) != 0) \
938817466cbSJens Wiklander { \
939817466cbSJens Wiklander if (verbose != 0) \
940817466cbSJens Wiklander mbedtls_printf("failed\n"); \
94132b31808SJens Wiklander return 1; \
942817466cbSJens Wiklander }
943817466cbSJens Wiklander
944039e02dfSJerome Forissier #define SELF_TEST_OUTPUT_DISCARD_LENGTH 64
9457901324dSJerome Forissier
946817466cbSJens Wiklander /*
947817466cbSJens Wiklander * Checkup routine
948817466cbSJens Wiklander */
mbedtls_ctr_drbg_self_test(int verbose)949817466cbSJens Wiklander int mbedtls_ctr_drbg_self_test(int verbose)
950817466cbSJens Wiklander {
951817466cbSJens Wiklander mbedtls_ctr_drbg_context ctx;
9527901324dSJerome Forissier unsigned char buf[sizeof(result_pr)];
953817466cbSJens Wiklander
954817466cbSJens Wiklander mbedtls_ctr_drbg_init(&ctx);
955817466cbSJens Wiklander
956817466cbSJens Wiklander /*
957817466cbSJens Wiklander * Based on a NIST CTR_DRBG test vector (PR = True)
958817466cbSJens Wiklander */
95932b31808SJens Wiklander if (verbose != 0) {
960817466cbSJens Wiklander mbedtls_printf(" CTR_DRBG (PR = TRUE) : ");
96132b31808SJens Wiklander }
962817466cbSJens Wiklander
963817466cbSJens Wiklander test_offset = 0;
9647901324dSJerome Forissier mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
9657901324dSJerome Forissier mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2);
9665b25c76aSJerome Forissier CHK(mbedtls_ctr_drbg_seed(&ctx,
9675b25c76aSJerome Forissier ctr_drbg_self_test_entropy,
9685b25c76aSJerome Forissier (void *) entropy_source_pr,
9697901324dSJerome Forissier pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE));
970817466cbSJens Wiklander mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_ON);
971039e02dfSJerome Forissier CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH));
9727901324dSJerome Forissier CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_pr)));
9737901324dSJerome Forissier CHK(memcmp(buf, result_pr, sizeof(result_pr)));
974817466cbSJens Wiklander
975817466cbSJens Wiklander mbedtls_ctr_drbg_free(&ctx);
976817466cbSJens Wiklander
97732b31808SJens Wiklander if (verbose != 0) {
978817466cbSJens Wiklander mbedtls_printf("passed\n");
97932b31808SJens Wiklander }
980817466cbSJens Wiklander
981817466cbSJens Wiklander /*
982817466cbSJens Wiklander * Based on a NIST CTR_DRBG test vector (PR = FALSE)
983817466cbSJens Wiklander */
98432b31808SJens Wiklander if (verbose != 0) {
985817466cbSJens Wiklander mbedtls_printf(" CTR_DRBG (PR = FALSE): ");
98632b31808SJens Wiklander }
987817466cbSJens Wiklander
988817466cbSJens Wiklander mbedtls_ctr_drbg_init(&ctx);
989817466cbSJens Wiklander
990817466cbSJens Wiklander test_offset = 0;
9917901324dSJerome Forissier mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
9927901324dSJerome Forissier mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2);
9935b25c76aSJerome Forissier CHK(mbedtls_ctr_drbg_seed(&ctx,
9945b25c76aSJerome Forissier ctr_drbg_self_test_entropy,
9955b25c76aSJerome Forissier (void *) entropy_source_nopr,
9967901324dSJerome Forissier pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE));
997817466cbSJens Wiklander CHK(mbedtls_ctr_drbg_reseed(&ctx, NULL, 0));
998039e02dfSJerome Forissier CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH));
9997901324dSJerome Forissier CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_nopr)));
10007901324dSJerome Forissier CHK(memcmp(buf, result_nopr, sizeof(result_nopr)));
1001817466cbSJens Wiklander
1002817466cbSJens Wiklander mbedtls_ctr_drbg_free(&ctx);
1003817466cbSJens Wiklander
100432b31808SJens Wiklander if (verbose != 0) {
1005817466cbSJens Wiklander mbedtls_printf("passed\n");
100632b31808SJens Wiklander }
1007817466cbSJens Wiklander
100832b31808SJens Wiklander if (verbose != 0) {
1009817466cbSJens Wiklander mbedtls_printf("\n");
101032b31808SJens Wiklander }
1011817466cbSJens Wiklander
101232b31808SJens Wiklander return 0;
1013817466cbSJens Wiklander }
1014817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST */
1015817466cbSJens Wiklander
1016817466cbSJens Wiklander #endif /* MBEDTLS_CTR_DRBG_C */
1017