1*62c56f98SSadaf Ebrahimi /*
2*62c56f98SSadaf Ebrahimi * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
3*62c56f98SSadaf Ebrahimi *
4*62c56f98SSadaf Ebrahimi * Copyright The Mbed TLS Contributors
5*62c56f98SSadaf Ebrahimi * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6*62c56f98SSadaf Ebrahimi */
7*62c56f98SSadaf Ebrahimi /*
8*62c56f98SSadaf Ebrahimi * The NIST SP 800-90 DRBGs are described in the following publication.
9*62c56f98SSadaf Ebrahimi *
10*62c56f98SSadaf Ebrahimi * https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-90r.pdf
11*62c56f98SSadaf Ebrahimi */
12*62c56f98SSadaf Ebrahimi
13*62c56f98SSadaf Ebrahimi #include "common.h"
14*62c56f98SSadaf Ebrahimi
15*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_CTR_DRBG_C)
16*62c56f98SSadaf Ebrahimi
17*62c56f98SSadaf Ebrahimi #include "mbedtls/ctr_drbg.h"
18*62c56f98SSadaf Ebrahimi #include "mbedtls/platform_util.h"
19*62c56f98SSadaf Ebrahimi #include "mbedtls/error.h"
20*62c56f98SSadaf Ebrahimi
21*62c56f98SSadaf Ebrahimi #include <string.h>
22*62c56f98SSadaf Ebrahimi
23*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_FS_IO)
24*62c56f98SSadaf Ebrahimi #include <stdio.h>
25*62c56f98SSadaf Ebrahimi #endif
26*62c56f98SSadaf Ebrahimi
27*62c56f98SSadaf Ebrahimi #include "mbedtls/platform.h"
28*62c56f98SSadaf Ebrahimi
29*62c56f98SSadaf Ebrahimi /*
30*62c56f98SSadaf Ebrahimi * CTR_DRBG context initialization
31*62c56f98SSadaf Ebrahimi */
mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context * ctx)32*62c56f98SSadaf Ebrahimi void mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context *ctx)
33*62c56f98SSadaf Ebrahimi {
34*62c56f98SSadaf Ebrahimi memset(ctx, 0, sizeof(mbedtls_ctr_drbg_context));
35*62c56f98SSadaf Ebrahimi mbedtls_aes_init(&ctx->aes_ctx);
36*62c56f98SSadaf Ebrahimi /* Indicate that the entropy nonce length is not set explicitly.
37*62c56f98SSadaf Ebrahimi * See mbedtls_ctr_drbg_set_nonce_len(). */
38*62c56f98SSadaf Ebrahimi ctx->reseed_counter = -1;
39*62c56f98SSadaf Ebrahimi
40*62c56f98SSadaf Ebrahimi ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
41*62c56f98SSadaf Ebrahimi }
42*62c56f98SSadaf Ebrahimi
43*62c56f98SSadaf Ebrahimi /*
44*62c56f98SSadaf Ebrahimi * This function resets CTR_DRBG context to the state immediately
45*62c56f98SSadaf Ebrahimi * after initial call of mbedtls_ctr_drbg_init().
46*62c56f98SSadaf Ebrahimi */
mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context * ctx)47*62c56f98SSadaf Ebrahimi void mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context *ctx)
48*62c56f98SSadaf Ebrahimi {
49*62c56f98SSadaf Ebrahimi if (ctx == NULL) {
50*62c56f98SSadaf Ebrahimi return;
51*62c56f98SSadaf Ebrahimi }
52*62c56f98SSadaf Ebrahimi
53*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_THREADING_C)
54*62c56f98SSadaf Ebrahimi /* The mutex is initialized iff f_entropy is set. */
55*62c56f98SSadaf Ebrahimi if (ctx->f_entropy != NULL) {
56*62c56f98SSadaf Ebrahimi mbedtls_mutex_free(&ctx->mutex);
57*62c56f98SSadaf Ebrahimi }
58*62c56f98SSadaf Ebrahimi #endif
59*62c56f98SSadaf Ebrahimi mbedtls_aes_free(&ctx->aes_ctx);
60*62c56f98SSadaf Ebrahimi mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ctr_drbg_context));
61*62c56f98SSadaf Ebrahimi ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
62*62c56f98SSadaf Ebrahimi ctx->reseed_counter = -1;
63*62c56f98SSadaf Ebrahimi }
64*62c56f98SSadaf Ebrahimi
mbedtls_ctr_drbg_set_prediction_resistance(mbedtls_ctr_drbg_context * ctx,int resistance)65*62c56f98SSadaf Ebrahimi void mbedtls_ctr_drbg_set_prediction_resistance(mbedtls_ctr_drbg_context *ctx,
66*62c56f98SSadaf Ebrahimi int resistance)
67*62c56f98SSadaf Ebrahimi {
68*62c56f98SSadaf Ebrahimi ctx->prediction_resistance = resistance;
69*62c56f98SSadaf Ebrahimi }
70*62c56f98SSadaf Ebrahimi
mbedtls_ctr_drbg_set_entropy_len(mbedtls_ctr_drbg_context * ctx,size_t len)71*62c56f98SSadaf Ebrahimi void mbedtls_ctr_drbg_set_entropy_len(mbedtls_ctr_drbg_context *ctx,
72*62c56f98SSadaf Ebrahimi size_t len)
73*62c56f98SSadaf Ebrahimi {
74*62c56f98SSadaf Ebrahimi ctx->entropy_len = len;
75*62c56f98SSadaf Ebrahimi }
76*62c56f98SSadaf Ebrahimi
mbedtls_ctr_drbg_set_nonce_len(mbedtls_ctr_drbg_context * ctx,size_t len)77*62c56f98SSadaf Ebrahimi int mbedtls_ctr_drbg_set_nonce_len(mbedtls_ctr_drbg_context *ctx,
78*62c56f98SSadaf Ebrahimi size_t len)
79*62c56f98SSadaf Ebrahimi {
80*62c56f98SSadaf Ebrahimi /* If mbedtls_ctr_drbg_seed() has already been called, it's
81*62c56f98SSadaf Ebrahimi * too late. Return the error code that's closest to making sense. */
82*62c56f98SSadaf Ebrahimi if (ctx->f_entropy != NULL) {
83*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
84*62c56f98SSadaf Ebrahimi }
85*62c56f98SSadaf Ebrahimi
86*62c56f98SSadaf Ebrahimi if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
87*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
88*62c56f98SSadaf Ebrahimi }
89*62c56f98SSadaf Ebrahimi
90*62c56f98SSadaf Ebrahimi /* This shouldn't be an issue because
91*62c56f98SSadaf Ebrahimi * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible
92*62c56f98SSadaf Ebrahimi * configuration, but make sure anyway. */
93*62c56f98SSadaf Ebrahimi if (len > INT_MAX) {
94*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
95*62c56f98SSadaf Ebrahimi }
96*62c56f98SSadaf Ebrahimi
97*62c56f98SSadaf Ebrahimi /* For backward compatibility with Mbed TLS <= 2.19, store the
98*62c56f98SSadaf Ebrahimi * entropy nonce length in a field that already exists, but isn't
99*62c56f98SSadaf Ebrahimi * used until after the initial seeding. */
100*62c56f98SSadaf Ebrahimi /* Due to the capping of len above, the value fits in an int. */
101*62c56f98SSadaf Ebrahimi ctx->reseed_counter = (int) len;
102*62c56f98SSadaf Ebrahimi return 0;
103*62c56f98SSadaf Ebrahimi }
104*62c56f98SSadaf Ebrahimi
mbedtls_ctr_drbg_set_reseed_interval(mbedtls_ctr_drbg_context * ctx,int interval)105*62c56f98SSadaf Ebrahimi void mbedtls_ctr_drbg_set_reseed_interval(mbedtls_ctr_drbg_context *ctx,
106*62c56f98SSadaf Ebrahimi int interval)
107*62c56f98SSadaf Ebrahimi {
108*62c56f98SSadaf Ebrahimi ctx->reseed_interval = interval;
109*62c56f98SSadaf Ebrahimi }
110*62c56f98SSadaf Ebrahimi
block_cipher_df(unsigned char * output,const unsigned char * data,size_t data_len)111*62c56f98SSadaf Ebrahimi static int block_cipher_df(unsigned char *output,
112*62c56f98SSadaf Ebrahimi const unsigned char *data, size_t data_len)
113*62c56f98SSadaf Ebrahimi {
114*62c56f98SSadaf Ebrahimi unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
115*62c56f98SSadaf Ebrahimi MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
116*62c56f98SSadaf Ebrahimi unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
117*62c56f98SSadaf Ebrahimi unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
118*62c56f98SSadaf Ebrahimi unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
119*62c56f98SSadaf Ebrahimi unsigned char *p, *iv;
120*62c56f98SSadaf Ebrahimi mbedtls_aes_context aes_ctx;
121*62c56f98SSadaf Ebrahimi int ret = 0;
122*62c56f98SSadaf Ebrahimi
123*62c56f98SSadaf Ebrahimi int i, j;
124*62c56f98SSadaf Ebrahimi size_t buf_len, use_len;
125*62c56f98SSadaf Ebrahimi
126*62c56f98SSadaf Ebrahimi if (data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
127*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
128*62c56f98SSadaf Ebrahimi }
129*62c56f98SSadaf Ebrahimi
130*62c56f98SSadaf Ebrahimi memset(buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
131*62c56f98SSadaf Ebrahimi MBEDTLS_CTR_DRBG_BLOCKSIZE + 16);
132*62c56f98SSadaf Ebrahimi mbedtls_aes_init(&aes_ctx);
133*62c56f98SSadaf Ebrahimi
134*62c56f98SSadaf Ebrahimi /*
135*62c56f98SSadaf Ebrahimi * Construct IV (16 bytes) and S in buffer
136*62c56f98SSadaf Ebrahimi * IV = Counter (in 32-bits) padded to 16 with zeroes
137*62c56f98SSadaf Ebrahimi * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
138*62c56f98SSadaf Ebrahimi * data || 0x80
139*62c56f98SSadaf Ebrahimi * (Total is padded to a multiple of 16-bytes with zeroes)
140*62c56f98SSadaf Ebrahimi */
141*62c56f98SSadaf Ebrahimi p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
142*62c56f98SSadaf Ebrahimi MBEDTLS_PUT_UINT32_BE(data_len, p, 0);
143*62c56f98SSadaf Ebrahimi p += 4 + 3;
144*62c56f98SSadaf Ebrahimi *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
145*62c56f98SSadaf Ebrahimi memcpy(p, data, data_len);
146*62c56f98SSadaf Ebrahimi p[data_len] = 0x80;
147*62c56f98SSadaf Ebrahimi
148*62c56f98SSadaf Ebrahimi buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
149*62c56f98SSadaf Ebrahimi
150*62c56f98SSadaf Ebrahimi for (i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++) {
151*62c56f98SSadaf Ebrahimi key[i] = i;
152*62c56f98SSadaf Ebrahimi }
153*62c56f98SSadaf Ebrahimi
154*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, key,
155*62c56f98SSadaf Ebrahimi MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
156*62c56f98SSadaf Ebrahimi goto exit;
157*62c56f98SSadaf Ebrahimi }
158*62c56f98SSadaf Ebrahimi
159*62c56f98SSadaf Ebrahimi /*
160*62c56f98SSadaf Ebrahimi * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
161*62c56f98SSadaf Ebrahimi */
162*62c56f98SSadaf Ebrahimi for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
163*62c56f98SSadaf Ebrahimi p = buf;
164*62c56f98SSadaf Ebrahimi memset(chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE);
165*62c56f98SSadaf Ebrahimi use_len = buf_len;
166*62c56f98SSadaf Ebrahimi
167*62c56f98SSadaf Ebrahimi while (use_len > 0) {
168*62c56f98SSadaf Ebrahimi mbedtls_xor(chain, chain, p, MBEDTLS_CTR_DRBG_BLOCKSIZE);
169*62c56f98SSadaf Ebrahimi p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
170*62c56f98SSadaf Ebrahimi use_len -= (use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE) ?
171*62c56f98SSadaf Ebrahimi MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
172*62c56f98SSadaf Ebrahimi
173*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,
174*62c56f98SSadaf Ebrahimi chain, chain)) != 0) {
175*62c56f98SSadaf Ebrahimi goto exit;
176*62c56f98SSadaf Ebrahimi }
177*62c56f98SSadaf Ebrahimi }
178*62c56f98SSadaf Ebrahimi
179*62c56f98SSadaf Ebrahimi memcpy(tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE);
180*62c56f98SSadaf Ebrahimi
181*62c56f98SSadaf Ebrahimi /*
182*62c56f98SSadaf Ebrahimi * Update IV
183*62c56f98SSadaf Ebrahimi */
184*62c56f98SSadaf Ebrahimi buf[3]++;
185*62c56f98SSadaf Ebrahimi }
186*62c56f98SSadaf Ebrahimi
187*62c56f98SSadaf Ebrahimi /*
188*62c56f98SSadaf Ebrahimi * Do final encryption with reduced data
189*62c56f98SSadaf Ebrahimi */
190*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, tmp,
191*62c56f98SSadaf Ebrahimi MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
192*62c56f98SSadaf Ebrahimi goto exit;
193*62c56f98SSadaf Ebrahimi }
194*62c56f98SSadaf Ebrahimi iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
195*62c56f98SSadaf Ebrahimi p = output;
196*62c56f98SSadaf Ebrahimi
197*62c56f98SSadaf Ebrahimi for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
198*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,
199*62c56f98SSadaf Ebrahimi iv, iv)) != 0) {
200*62c56f98SSadaf Ebrahimi goto exit;
201*62c56f98SSadaf Ebrahimi }
202*62c56f98SSadaf Ebrahimi memcpy(p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE);
203*62c56f98SSadaf Ebrahimi p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
204*62c56f98SSadaf Ebrahimi }
205*62c56f98SSadaf Ebrahimi exit:
206*62c56f98SSadaf Ebrahimi mbedtls_aes_free(&aes_ctx);
207*62c56f98SSadaf Ebrahimi /*
208*62c56f98SSadaf Ebrahimi * tidy up the stack
209*62c56f98SSadaf Ebrahimi */
210*62c56f98SSadaf Ebrahimi mbedtls_platform_zeroize(buf, sizeof(buf));
211*62c56f98SSadaf Ebrahimi mbedtls_platform_zeroize(tmp, sizeof(tmp));
212*62c56f98SSadaf Ebrahimi mbedtls_platform_zeroize(key, sizeof(key));
213*62c56f98SSadaf Ebrahimi mbedtls_platform_zeroize(chain, sizeof(chain));
214*62c56f98SSadaf Ebrahimi if (0 != ret) {
215*62c56f98SSadaf Ebrahimi /*
216*62c56f98SSadaf Ebrahimi * wipe partial seed from memory
217*62c56f98SSadaf Ebrahimi */
218*62c56f98SSadaf Ebrahimi mbedtls_platform_zeroize(output, MBEDTLS_CTR_DRBG_SEEDLEN);
219*62c56f98SSadaf Ebrahimi }
220*62c56f98SSadaf Ebrahimi
221*62c56f98SSadaf Ebrahimi return ret;
222*62c56f98SSadaf Ebrahimi }
223*62c56f98SSadaf Ebrahimi
224*62c56f98SSadaf Ebrahimi /* CTR_DRBG_Update (SP 800-90A §10.2.1.2)
225*62c56f98SSadaf Ebrahimi * ctr_drbg_update_internal(ctx, provided_data)
226*62c56f98SSadaf Ebrahimi * implements
227*62c56f98SSadaf Ebrahimi * CTR_DRBG_Update(provided_data, Key, V)
228*62c56f98SSadaf Ebrahimi * with inputs and outputs
229*62c56f98SSadaf Ebrahimi * ctx->aes_ctx = Key
230*62c56f98SSadaf Ebrahimi * ctx->counter = V
231*62c56f98SSadaf Ebrahimi */
ctr_drbg_update_internal(mbedtls_ctr_drbg_context * ctx,const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN])232*62c56f98SSadaf Ebrahimi static int ctr_drbg_update_internal(mbedtls_ctr_drbg_context *ctx,
233*62c56f98SSadaf Ebrahimi const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN])
234*62c56f98SSadaf Ebrahimi {
235*62c56f98SSadaf Ebrahimi unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
236*62c56f98SSadaf Ebrahimi unsigned char *p = tmp;
237*62c56f98SSadaf Ebrahimi int i, j;
238*62c56f98SSadaf Ebrahimi int ret = 0;
239*62c56f98SSadaf Ebrahimi
240*62c56f98SSadaf Ebrahimi memset(tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN);
241*62c56f98SSadaf Ebrahimi
242*62c56f98SSadaf Ebrahimi for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
243*62c56f98SSadaf Ebrahimi /*
244*62c56f98SSadaf Ebrahimi * Increase counter
245*62c56f98SSadaf Ebrahimi */
246*62c56f98SSadaf Ebrahimi for (i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i--) {
247*62c56f98SSadaf Ebrahimi if (++ctx->counter[i - 1] != 0) {
248*62c56f98SSadaf Ebrahimi break;
249*62c56f98SSadaf Ebrahimi }
250*62c56f98SSadaf Ebrahimi }
251*62c56f98SSadaf Ebrahimi
252*62c56f98SSadaf Ebrahimi /*
253*62c56f98SSadaf Ebrahimi * Crypt counter block
254*62c56f98SSadaf Ebrahimi */
255*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
256*62c56f98SSadaf Ebrahimi ctx->counter, p)) != 0) {
257*62c56f98SSadaf Ebrahimi goto exit;
258*62c56f98SSadaf Ebrahimi }
259*62c56f98SSadaf Ebrahimi
260*62c56f98SSadaf Ebrahimi p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
261*62c56f98SSadaf Ebrahimi }
262*62c56f98SSadaf Ebrahimi
263*62c56f98SSadaf Ebrahimi for (i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++) {
264*62c56f98SSadaf Ebrahimi tmp[i] ^= data[i];
265*62c56f98SSadaf Ebrahimi }
266*62c56f98SSadaf Ebrahimi
267*62c56f98SSadaf Ebrahimi /*
268*62c56f98SSadaf Ebrahimi * Update key and counter
269*62c56f98SSadaf Ebrahimi */
270*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, tmp,
271*62c56f98SSadaf Ebrahimi MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
272*62c56f98SSadaf Ebrahimi goto exit;
273*62c56f98SSadaf Ebrahimi }
274*62c56f98SSadaf Ebrahimi memcpy(ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
275*62c56f98SSadaf Ebrahimi MBEDTLS_CTR_DRBG_BLOCKSIZE);
276*62c56f98SSadaf Ebrahimi
277*62c56f98SSadaf Ebrahimi exit:
278*62c56f98SSadaf Ebrahimi mbedtls_platform_zeroize(tmp, sizeof(tmp));
279*62c56f98SSadaf Ebrahimi return ret;
280*62c56f98SSadaf Ebrahimi }
281*62c56f98SSadaf Ebrahimi
282*62c56f98SSadaf Ebrahimi /* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2)
283*62c56f98SSadaf Ebrahimi * mbedtls_ctr_drbg_update(ctx, additional, add_len)
284*62c56f98SSadaf Ebrahimi * implements
285*62c56f98SSadaf Ebrahimi * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
286*62c56f98SSadaf Ebrahimi * security_strength) -> initial_working_state
287*62c56f98SSadaf Ebrahimi * with inputs
288*62c56f98SSadaf Ebrahimi * ctx->counter = all-bits-0
289*62c56f98SSadaf Ebrahimi * ctx->aes_ctx = context from all-bits-0 key
290*62c56f98SSadaf Ebrahimi * additional[:add_len] = entropy_input || nonce || personalization_string
291*62c56f98SSadaf Ebrahimi * and with outputs
292*62c56f98SSadaf Ebrahimi * ctx = initial_working_state
293*62c56f98SSadaf Ebrahimi */
mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context * ctx,const unsigned char * additional,size_t add_len)294*62c56f98SSadaf Ebrahimi int mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context *ctx,
295*62c56f98SSadaf Ebrahimi const unsigned char *additional,
296*62c56f98SSadaf Ebrahimi size_t add_len)
297*62c56f98SSadaf Ebrahimi {
298*62c56f98SSadaf Ebrahimi unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
299*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
300*62c56f98SSadaf Ebrahimi
301*62c56f98SSadaf Ebrahimi if (add_len == 0) {
302*62c56f98SSadaf Ebrahimi return 0;
303*62c56f98SSadaf Ebrahimi }
304*62c56f98SSadaf Ebrahimi
305*62c56f98SSadaf Ebrahimi if ((ret = block_cipher_df(add_input, additional, add_len)) != 0) {
306*62c56f98SSadaf Ebrahimi goto exit;
307*62c56f98SSadaf Ebrahimi }
308*62c56f98SSadaf Ebrahimi if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {
309*62c56f98SSadaf Ebrahimi goto exit;
310*62c56f98SSadaf Ebrahimi }
311*62c56f98SSadaf Ebrahimi
312*62c56f98SSadaf Ebrahimi exit:
313*62c56f98SSadaf Ebrahimi mbedtls_platform_zeroize(add_input, sizeof(add_input));
314*62c56f98SSadaf Ebrahimi return ret;
315*62c56f98SSadaf Ebrahimi }
316*62c56f98SSadaf Ebrahimi
317*62c56f98SSadaf Ebrahimi /* CTR_DRBG_Reseed with derivation function (SP 800-90A §10.2.1.4.2)
318*62c56f98SSadaf Ebrahimi * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
319*62c56f98SSadaf Ebrahimi * implements
320*62c56f98SSadaf Ebrahimi * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
321*62c56f98SSadaf Ebrahimi * -> new_working_state
322*62c56f98SSadaf Ebrahimi * with inputs
323*62c56f98SSadaf Ebrahimi * ctx contains working_state
324*62c56f98SSadaf Ebrahimi * additional[:len] = additional_input
325*62c56f98SSadaf Ebrahimi * and entropy_input comes from calling ctx->f_entropy
326*62c56f98SSadaf Ebrahimi * for (ctx->entropy_len + nonce_len) bytes
327*62c56f98SSadaf Ebrahimi * and with output
328*62c56f98SSadaf Ebrahimi * ctx contains new_working_state
329*62c56f98SSadaf Ebrahimi */
mbedtls_ctr_drbg_reseed_internal(mbedtls_ctr_drbg_context * ctx,const unsigned char * additional,size_t len,size_t nonce_len)330*62c56f98SSadaf Ebrahimi static int mbedtls_ctr_drbg_reseed_internal(mbedtls_ctr_drbg_context *ctx,
331*62c56f98SSadaf Ebrahimi const unsigned char *additional,
332*62c56f98SSadaf Ebrahimi size_t len,
333*62c56f98SSadaf Ebrahimi size_t nonce_len)
334*62c56f98SSadaf Ebrahimi {
335*62c56f98SSadaf Ebrahimi unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
336*62c56f98SSadaf Ebrahimi size_t seedlen = 0;
337*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
338*62c56f98SSadaf Ebrahimi
339*62c56f98SSadaf Ebrahimi if (ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
340*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
341*62c56f98SSadaf Ebrahimi }
342*62c56f98SSadaf Ebrahimi if (nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len) {
343*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
344*62c56f98SSadaf Ebrahimi }
345*62c56f98SSadaf Ebrahimi if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len) {
346*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
347*62c56f98SSadaf Ebrahimi }
348*62c56f98SSadaf Ebrahimi
349*62c56f98SSadaf Ebrahimi memset(seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT);
350*62c56f98SSadaf Ebrahimi
351*62c56f98SSadaf Ebrahimi /* Gather entropy_len bytes of entropy to seed state. */
352*62c56f98SSadaf Ebrahimi if (0 != ctx->f_entropy(ctx->p_entropy, seed, ctx->entropy_len)) {
353*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
354*62c56f98SSadaf Ebrahimi }
355*62c56f98SSadaf Ebrahimi seedlen += ctx->entropy_len;
356*62c56f98SSadaf Ebrahimi
357*62c56f98SSadaf Ebrahimi /* Gather entropy for a nonce if requested. */
358*62c56f98SSadaf Ebrahimi if (nonce_len != 0) {
359*62c56f98SSadaf Ebrahimi if (0 != ctx->f_entropy(ctx->p_entropy, seed + seedlen, nonce_len)) {
360*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
361*62c56f98SSadaf Ebrahimi }
362*62c56f98SSadaf Ebrahimi seedlen += nonce_len;
363*62c56f98SSadaf Ebrahimi }
364*62c56f98SSadaf Ebrahimi
365*62c56f98SSadaf Ebrahimi /* Add additional data if provided. */
366*62c56f98SSadaf Ebrahimi if (additional != NULL && len != 0) {
367*62c56f98SSadaf Ebrahimi memcpy(seed + seedlen, additional, len);
368*62c56f98SSadaf Ebrahimi seedlen += len;
369*62c56f98SSadaf Ebrahimi }
370*62c56f98SSadaf Ebrahimi
371*62c56f98SSadaf Ebrahimi /* Reduce to 384 bits. */
372*62c56f98SSadaf Ebrahimi if ((ret = block_cipher_df(seed, seed, seedlen)) != 0) {
373*62c56f98SSadaf Ebrahimi goto exit;
374*62c56f98SSadaf Ebrahimi }
375*62c56f98SSadaf Ebrahimi
376*62c56f98SSadaf Ebrahimi /* Update state. */
377*62c56f98SSadaf Ebrahimi if ((ret = ctr_drbg_update_internal(ctx, seed)) != 0) {
378*62c56f98SSadaf Ebrahimi goto exit;
379*62c56f98SSadaf Ebrahimi }
380*62c56f98SSadaf Ebrahimi ctx->reseed_counter = 1;
381*62c56f98SSadaf Ebrahimi
382*62c56f98SSadaf Ebrahimi exit:
383*62c56f98SSadaf Ebrahimi mbedtls_platform_zeroize(seed, sizeof(seed));
384*62c56f98SSadaf Ebrahimi return ret;
385*62c56f98SSadaf Ebrahimi }
386*62c56f98SSadaf Ebrahimi
mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context * ctx,const unsigned char * additional,size_t len)387*62c56f98SSadaf Ebrahimi int mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context *ctx,
388*62c56f98SSadaf Ebrahimi const unsigned char *additional, size_t len)
389*62c56f98SSadaf Ebrahimi {
390*62c56f98SSadaf Ebrahimi return mbedtls_ctr_drbg_reseed_internal(ctx, additional, len, 0);
391*62c56f98SSadaf Ebrahimi }
392*62c56f98SSadaf Ebrahimi
393*62c56f98SSadaf Ebrahimi /* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
394*62c56f98SSadaf Ebrahimi * is sufficient to achieve the maximum security strength given the key
395*62c56f98SSadaf Ebrahimi * size and entropy length. If there is enough entropy in the initial
396*62c56f98SSadaf Ebrahimi * call to the entropy function to serve as both the entropy input and
397*62c56f98SSadaf Ebrahimi * the nonce, don't make a second call to get a nonce. */
good_nonce_len(size_t entropy_len)398*62c56f98SSadaf Ebrahimi static size_t good_nonce_len(size_t entropy_len)
399*62c56f98SSadaf Ebrahimi {
400*62c56f98SSadaf Ebrahimi if (entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2) {
401*62c56f98SSadaf Ebrahimi return 0;
402*62c56f98SSadaf Ebrahimi } else {
403*62c56f98SSadaf Ebrahimi return (entropy_len + 1) / 2;
404*62c56f98SSadaf Ebrahimi }
405*62c56f98SSadaf Ebrahimi }
406*62c56f98SSadaf Ebrahimi
407*62c56f98SSadaf Ebrahimi /* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2)
408*62c56f98SSadaf Ebrahimi * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
409*62c56f98SSadaf Ebrahimi * implements
410*62c56f98SSadaf Ebrahimi * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
411*62c56f98SSadaf Ebrahimi * security_strength) -> initial_working_state
412*62c56f98SSadaf Ebrahimi * with inputs
413*62c56f98SSadaf Ebrahimi * custom[:len] = nonce || personalization_string
414*62c56f98SSadaf Ebrahimi * where entropy_input comes from f_entropy for ctx->entropy_len bytes
415*62c56f98SSadaf Ebrahimi * and with outputs
416*62c56f98SSadaf Ebrahimi * ctx = initial_working_state
417*62c56f98SSadaf Ebrahimi */
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)418*62c56f98SSadaf Ebrahimi int mbedtls_ctr_drbg_seed(mbedtls_ctr_drbg_context *ctx,
419*62c56f98SSadaf Ebrahimi int (*f_entropy)(void *, unsigned char *, size_t),
420*62c56f98SSadaf Ebrahimi void *p_entropy,
421*62c56f98SSadaf Ebrahimi const unsigned char *custom,
422*62c56f98SSadaf Ebrahimi size_t len)
423*62c56f98SSadaf Ebrahimi {
424*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
425*62c56f98SSadaf Ebrahimi unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
426*62c56f98SSadaf Ebrahimi size_t nonce_len;
427*62c56f98SSadaf Ebrahimi
428*62c56f98SSadaf Ebrahimi memset(key, 0, MBEDTLS_CTR_DRBG_KEYSIZE);
429*62c56f98SSadaf Ebrahimi
430*62c56f98SSadaf Ebrahimi /* The mutex is initialized iff f_entropy is set. */
431*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_THREADING_C)
432*62c56f98SSadaf Ebrahimi mbedtls_mutex_init(&ctx->mutex);
433*62c56f98SSadaf Ebrahimi #endif
434*62c56f98SSadaf Ebrahimi
435*62c56f98SSadaf Ebrahimi ctx->f_entropy = f_entropy;
436*62c56f98SSadaf Ebrahimi ctx->p_entropy = p_entropy;
437*62c56f98SSadaf Ebrahimi
438*62c56f98SSadaf Ebrahimi if (ctx->entropy_len == 0) {
439*62c56f98SSadaf Ebrahimi ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
440*62c56f98SSadaf Ebrahimi }
441*62c56f98SSadaf Ebrahimi /* ctx->reseed_counter contains the desired amount of entropy to
442*62c56f98SSadaf Ebrahimi * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
443*62c56f98SSadaf Ebrahimi * If it's -1, indicating that the entropy nonce length was not set
444*62c56f98SSadaf Ebrahimi * explicitly, use a sufficiently large nonce for security. */
445*62c56f98SSadaf Ebrahimi nonce_len = (ctx->reseed_counter >= 0 ?
446*62c56f98SSadaf Ebrahimi (size_t) ctx->reseed_counter :
447*62c56f98SSadaf Ebrahimi good_nonce_len(ctx->entropy_len));
448*62c56f98SSadaf Ebrahimi
449*62c56f98SSadaf Ebrahimi /* Initialize with an empty key. */
450*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, key,
451*62c56f98SSadaf Ebrahimi MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
452*62c56f98SSadaf Ebrahimi return ret;
453*62c56f98SSadaf Ebrahimi }
454*62c56f98SSadaf Ebrahimi
455*62c56f98SSadaf Ebrahimi /* Do the initial seeding. */
456*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_ctr_drbg_reseed_internal(ctx, custom, len,
457*62c56f98SSadaf Ebrahimi nonce_len)) != 0) {
458*62c56f98SSadaf Ebrahimi return ret;
459*62c56f98SSadaf Ebrahimi }
460*62c56f98SSadaf Ebrahimi return 0;
461*62c56f98SSadaf Ebrahimi }
462*62c56f98SSadaf Ebrahimi
463*62c56f98SSadaf Ebrahimi /* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2)
464*62c56f98SSadaf Ebrahimi * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
465*62c56f98SSadaf Ebrahimi * implements
466*62c56f98SSadaf Ebrahimi * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
467*62c56f98SSadaf Ebrahimi * -> working_state_after_reseed
468*62c56f98SSadaf Ebrahimi * if required, then
469*62c56f98SSadaf Ebrahimi * CTR_DRBG_Generate(working_state_after_reseed,
470*62c56f98SSadaf Ebrahimi * requested_number_of_bits, additional_input)
471*62c56f98SSadaf Ebrahimi * -> status, returned_bits, new_working_state
472*62c56f98SSadaf Ebrahimi * with inputs
473*62c56f98SSadaf Ebrahimi * ctx contains working_state
474*62c56f98SSadaf Ebrahimi * requested_number_of_bits = 8 * output_len
475*62c56f98SSadaf Ebrahimi * additional[:add_len] = additional_input
476*62c56f98SSadaf Ebrahimi * and entropy_input comes from calling ctx->f_entropy
477*62c56f98SSadaf Ebrahimi * and with outputs
478*62c56f98SSadaf Ebrahimi * status = SUCCESS (this function does the reseed internally)
479*62c56f98SSadaf Ebrahimi * returned_bits = output[:output_len]
480*62c56f98SSadaf Ebrahimi * ctx contains new_working_state
481*62c56f98SSadaf Ebrahimi */
mbedtls_ctr_drbg_random_with_add(void * p_rng,unsigned char * output,size_t output_len,const unsigned char * additional,size_t add_len)482*62c56f98SSadaf Ebrahimi int mbedtls_ctr_drbg_random_with_add(void *p_rng,
483*62c56f98SSadaf Ebrahimi unsigned char *output, size_t output_len,
484*62c56f98SSadaf Ebrahimi const unsigned char *additional, size_t add_len)
485*62c56f98SSadaf Ebrahimi {
486*62c56f98SSadaf Ebrahimi int ret = 0;
487*62c56f98SSadaf Ebrahimi mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
488*62c56f98SSadaf Ebrahimi unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
489*62c56f98SSadaf Ebrahimi unsigned char *p = output;
490*62c56f98SSadaf Ebrahimi unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
491*62c56f98SSadaf Ebrahimi int i;
492*62c56f98SSadaf Ebrahimi size_t use_len;
493*62c56f98SSadaf Ebrahimi
494*62c56f98SSadaf Ebrahimi if (output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST) {
495*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG;
496*62c56f98SSadaf Ebrahimi }
497*62c56f98SSadaf Ebrahimi
498*62c56f98SSadaf Ebrahimi if (add_len > MBEDTLS_CTR_DRBG_MAX_INPUT) {
499*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
500*62c56f98SSadaf Ebrahimi }
501*62c56f98SSadaf Ebrahimi
502*62c56f98SSadaf Ebrahimi memset(add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN);
503*62c56f98SSadaf Ebrahimi
504*62c56f98SSadaf Ebrahimi if (ctx->reseed_counter > ctx->reseed_interval ||
505*62c56f98SSadaf Ebrahimi ctx->prediction_resistance) {
506*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_ctr_drbg_reseed(ctx, additional, add_len)) != 0) {
507*62c56f98SSadaf Ebrahimi return ret;
508*62c56f98SSadaf Ebrahimi }
509*62c56f98SSadaf Ebrahimi add_len = 0;
510*62c56f98SSadaf Ebrahimi }
511*62c56f98SSadaf Ebrahimi
512*62c56f98SSadaf Ebrahimi if (add_len > 0) {
513*62c56f98SSadaf Ebrahimi if ((ret = block_cipher_df(add_input, additional, add_len)) != 0) {
514*62c56f98SSadaf Ebrahimi goto exit;
515*62c56f98SSadaf Ebrahimi }
516*62c56f98SSadaf Ebrahimi if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {
517*62c56f98SSadaf Ebrahimi goto exit;
518*62c56f98SSadaf Ebrahimi }
519*62c56f98SSadaf Ebrahimi }
520*62c56f98SSadaf Ebrahimi
521*62c56f98SSadaf Ebrahimi while (output_len > 0) {
522*62c56f98SSadaf Ebrahimi /*
523*62c56f98SSadaf Ebrahimi * Increase counter
524*62c56f98SSadaf Ebrahimi */
525*62c56f98SSadaf Ebrahimi for (i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i--) {
526*62c56f98SSadaf Ebrahimi if (++ctx->counter[i - 1] != 0) {
527*62c56f98SSadaf Ebrahimi break;
528*62c56f98SSadaf Ebrahimi }
529*62c56f98SSadaf Ebrahimi }
530*62c56f98SSadaf Ebrahimi
531*62c56f98SSadaf Ebrahimi /*
532*62c56f98SSadaf Ebrahimi * Crypt counter block
533*62c56f98SSadaf Ebrahimi */
534*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
535*62c56f98SSadaf Ebrahimi ctx->counter, tmp)) != 0) {
536*62c56f98SSadaf Ebrahimi goto exit;
537*62c56f98SSadaf Ebrahimi }
538*62c56f98SSadaf Ebrahimi
539*62c56f98SSadaf Ebrahimi use_len = (output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE)
540*62c56f98SSadaf Ebrahimi ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
541*62c56f98SSadaf Ebrahimi /*
542*62c56f98SSadaf Ebrahimi * Copy random block to destination
543*62c56f98SSadaf Ebrahimi */
544*62c56f98SSadaf Ebrahimi memcpy(p, tmp, use_len);
545*62c56f98SSadaf Ebrahimi p += use_len;
546*62c56f98SSadaf Ebrahimi output_len -= use_len;
547*62c56f98SSadaf Ebrahimi }
548*62c56f98SSadaf Ebrahimi
549*62c56f98SSadaf Ebrahimi if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {
550*62c56f98SSadaf Ebrahimi goto exit;
551*62c56f98SSadaf Ebrahimi }
552*62c56f98SSadaf Ebrahimi
553*62c56f98SSadaf Ebrahimi ctx->reseed_counter++;
554*62c56f98SSadaf Ebrahimi
555*62c56f98SSadaf Ebrahimi exit:
556*62c56f98SSadaf Ebrahimi mbedtls_platform_zeroize(add_input, sizeof(add_input));
557*62c56f98SSadaf Ebrahimi mbedtls_platform_zeroize(tmp, sizeof(tmp));
558*62c56f98SSadaf Ebrahimi return ret;
559*62c56f98SSadaf Ebrahimi }
560*62c56f98SSadaf Ebrahimi
mbedtls_ctr_drbg_random(void * p_rng,unsigned char * output,size_t output_len)561*62c56f98SSadaf Ebrahimi int mbedtls_ctr_drbg_random(void *p_rng, unsigned char *output,
562*62c56f98SSadaf Ebrahimi size_t output_len)
563*62c56f98SSadaf Ebrahimi {
564*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
565*62c56f98SSadaf Ebrahimi mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
566*62c56f98SSadaf Ebrahimi
567*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_THREADING_C)
568*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
569*62c56f98SSadaf Ebrahimi return ret;
570*62c56f98SSadaf Ebrahimi }
571*62c56f98SSadaf Ebrahimi #endif
572*62c56f98SSadaf Ebrahimi
573*62c56f98SSadaf Ebrahimi ret = mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, NULL, 0);
574*62c56f98SSadaf Ebrahimi
575*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_THREADING_C)
576*62c56f98SSadaf Ebrahimi if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
577*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
578*62c56f98SSadaf Ebrahimi }
579*62c56f98SSadaf Ebrahimi #endif
580*62c56f98SSadaf Ebrahimi
581*62c56f98SSadaf Ebrahimi return ret;
582*62c56f98SSadaf Ebrahimi }
583*62c56f98SSadaf Ebrahimi
584*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_FS_IO)
mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context * ctx,const char * path)585*62c56f98SSadaf Ebrahimi int mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context *ctx,
586*62c56f98SSadaf Ebrahimi const char *path)
587*62c56f98SSadaf Ebrahimi {
588*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
589*62c56f98SSadaf Ebrahimi FILE *f;
590*62c56f98SSadaf Ebrahimi unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT];
591*62c56f98SSadaf Ebrahimi
592*62c56f98SSadaf Ebrahimi if ((f = fopen(path, "wb")) == NULL) {
593*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
594*62c56f98SSadaf Ebrahimi }
595*62c56f98SSadaf Ebrahimi
596*62c56f98SSadaf Ebrahimi /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
597*62c56f98SSadaf Ebrahimi mbedtls_setbuf(f, NULL);
598*62c56f98SSadaf Ebrahimi
599*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_ctr_drbg_random(ctx, buf,
600*62c56f98SSadaf Ebrahimi MBEDTLS_CTR_DRBG_MAX_INPUT)) != 0) {
601*62c56f98SSadaf Ebrahimi goto exit;
602*62c56f98SSadaf Ebrahimi }
603*62c56f98SSadaf Ebrahimi
604*62c56f98SSadaf Ebrahimi if (fwrite(buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f) !=
605*62c56f98SSadaf Ebrahimi MBEDTLS_CTR_DRBG_MAX_INPUT) {
606*62c56f98SSadaf Ebrahimi ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
607*62c56f98SSadaf Ebrahimi } else {
608*62c56f98SSadaf Ebrahimi ret = 0;
609*62c56f98SSadaf Ebrahimi }
610*62c56f98SSadaf Ebrahimi
611*62c56f98SSadaf Ebrahimi exit:
612*62c56f98SSadaf Ebrahimi mbedtls_platform_zeroize(buf, sizeof(buf));
613*62c56f98SSadaf Ebrahimi
614*62c56f98SSadaf Ebrahimi fclose(f);
615*62c56f98SSadaf Ebrahimi return ret;
616*62c56f98SSadaf Ebrahimi }
617*62c56f98SSadaf Ebrahimi
mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context * ctx,const char * path)618*62c56f98SSadaf Ebrahimi int mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context *ctx,
619*62c56f98SSadaf Ebrahimi const char *path)
620*62c56f98SSadaf Ebrahimi {
621*62c56f98SSadaf Ebrahimi int ret = 0;
622*62c56f98SSadaf Ebrahimi FILE *f = NULL;
623*62c56f98SSadaf Ebrahimi size_t n;
624*62c56f98SSadaf Ebrahimi unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT];
625*62c56f98SSadaf Ebrahimi unsigned char c;
626*62c56f98SSadaf Ebrahimi
627*62c56f98SSadaf Ebrahimi if ((f = fopen(path, "rb")) == NULL) {
628*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
629*62c56f98SSadaf Ebrahimi }
630*62c56f98SSadaf Ebrahimi
631*62c56f98SSadaf Ebrahimi /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
632*62c56f98SSadaf Ebrahimi mbedtls_setbuf(f, NULL);
633*62c56f98SSadaf Ebrahimi
634*62c56f98SSadaf Ebrahimi n = fread(buf, 1, sizeof(buf), f);
635*62c56f98SSadaf Ebrahimi if (fread(&c, 1, 1, f) != 0) {
636*62c56f98SSadaf Ebrahimi ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
637*62c56f98SSadaf Ebrahimi goto exit;
638*62c56f98SSadaf Ebrahimi }
639*62c56f98SSadaf Ebrahimi if (n == 0 || ferror(f)) {
640*62c56f98SSadaf Ebrahimi ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
641*62c56f98SSadaf Ebrahimi goto exit;
642*62c56f98SSadaf Ebrahimi }
643*62c56f98SSadaf Ebrahimi fclose(f);
644*62c56f98SSadaf Ebrahimi f = NULL;
645*62c56f98SSadaf Ebrahimi
646*62c56f98SSadaf Ebrahimi ret = mbedtls_ctr_drbg_update(ctx, buf, n);
647*62c56f98SSadaf Ebrahimi
648*62c56f98SSadaf Ebrahimi exit:
649*62c56f98SSadaf Ebrahimi mbedtls_platform_zeroize(buf, sizeof(buf));
650*62c56f98SSadaf Ebrahimi if (f != NULL) {
651*62c56f98SSadaf Ebrahimi fclose(f);
652*62c56f98SSadaf Ebrahimi }
653*62c56f98SSadaf Ebrahimi if (ret != 0) {
654*62c56f98SSadaf Ebrahimi return ret;
655*62c56f98SSadaf Ebrahimi }
656*62c56f98SSadaf Ebrahimi return mbedtls_ctr_drbg_write_seed_file(ctx, path);
657*62c56f98SSadaf Ebrahimi }
658*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_FS_IO */
659*62c56f98SSadaf Ebrahimi
660*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_SELF_TEST)
661*62c56f98SSadaf Ebrahimi
662*62c56f98SSadaf Ebrahimi /* The CTR_DRBG NIST test vectors used here are available at
663*62c56f98SSadaf Ebrahimi * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip
664*62c56f98SSadaf Ebrahimi *
665*62c56f98SSadaf Ebrahimi * The parameters used to derive the test data are:
666*62c56f98SSadaf Ebrahimi *
667*62c56f98SSadaf Ebrahimi * [AES-128 use df]
668*62c56f98SSadaf Ebrahimi * [PredictionResistance = True/False]
669*62c56f98SSadaf Ebrahimi * [EntropyInputLen = 128]
670*62c56f98SSadaf Ebrahimi * [NonceLen = 64]
671*62c56f98SSadaf Ebrahimi * [PersonalizationStringLen = 128]
672*62c56f98SSadaf Ebrahimi * [AdditionalInputLen = 0]
673*62c56f98SSadaf Ebrahimi * [ReturnedBitsLen = 512]
674*62c56f98SSadaf Ebrahimi *
675*62c56f98SSadaf Ebrahimi * [AES-256 use df]
676*62c56f98SSadaf Ebrahimi * [PredictionResistance = True/False]
677*62c56f98SSadaf Ebrahimi * [EntropyInputLen = 256]
678*62c56f98SSadaf Ebrahimi * [NonceLen = 128]
679*62c56f98SSadaf Ebrahimi * [PersonalizationStringLen = 256]
680*62c56f98SSadaf Ebrahimi * [AdditionalInputLen = 0]
681*62c56f98SSadaf Ebrahimi * [ReturnedBitsLen = 512]
682*62c56f98SSadaf Ebrahimi *
683*62c56f98SSadaf Ebrahimi */
684*62c56f98SSadaf Ebrahimi
685*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
686*62c56f98SSadaf Ebrahimi static const unsigned char entropy_source_pr[] =
687*62c56f98SSadaf Ebrahimi { 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb,
688*62c56f98SSadaf Ebrahimi 0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92,
689*62c56f98SSadaf Ebrahimi 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8,
690*62c56f98SSadaf Ebrahimi 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20,
691*62c56f98SSadaf Ebrahimi 0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0,
692*62c56f98SSadaf Ebrahimi 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad,
693*62c56f98SSadaf Ebrahimi 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 };
694*62c56f98SSadaf Ebrahimi
695*62c56f98SSadaf Ebrahimi static const unsigned char entropy_source_nopr[] =
696*62c56f98SSadaf Ebrahimi { 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45,
697*62c56f98SSadaf Ebrahimi 0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9,
698*62c56f98SSadaf Ebrahimi 0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20,
699*62c56f98SSadaf Ebrahimi 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f,
700*62c56f98SSadaf Ebrahimi 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c };
701*62c56f98SSadaf Ebrahimi
702*62c56f98SSadaf Ebrahimi static const unsigned char pers_pr[] =
703*62c56f98SSadaf Ebrahimi { 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a,
704*62c56f98SSadaf Ebrahimi 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad };
705*62c56f98SSadaf Ebrahimi
706*62c56f98SSadaf Ebrahimi static const unsigned char pers_nopr[] =
707*62c56f98SSadaf Ebrahimi { 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c,
708*62c56f98SSadaf Ebrahimi 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f };
709*62c56f98SSadaf Ebrahimi
710*62c56f98SSadaf Ebrahimi static const unsigned char result_pr[] =
711*62c56f98SSadaf Ebrahimi { 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66,
712*62c56f98SSadaf Ebrahimi 0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff,
713*62c56f98SSadaf Ebrahimi 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10,
714*62c56f98SSadaf Ebrahimi 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30,
715*62c56f98SSadaf Ebrahimi 0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4,
716*62c56f98SSadaf Ebrahimi 0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc,
717*62c56f98SSadaf Ebrahimi 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06,
718*62c56f98SSadaf Ebrahimi 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf };
719*62c56f98SSadaf Ebrahimi
720*62c56f98SSadaf Ebrahimi static const unsigned char result_nopr[] =
721*62c56f98SSadaf Ebrahimi { 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13,
722*62c56f98SSadaf Ebrahimi 0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0,
723*62c56f98SSadaf Ebrahimi 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf,
724*62c56f98SSadaf Ebrahimi 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2,
725*62c56f98SSadaf Ebrahimi 0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7,
726*62c56f98SSadaf Ebrahimi 0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2,
727*62c56f98SSadaf Ebrahimi 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02,
728*62c56f98SSadaf Ebrahimi 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 };
729*62c56f98SSadaf Ebrahimi #else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
730*62c56f98SSadaf Ebrahimi
731*62c56f98SSadaf Ebrahimi static const unsigned char entropy_source_pr[] =
732*62c56f98SSadaf Ebrahimi { 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49,
733*62c56f98SSadaf Ebrahimi 0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a,
734*62c56f98SSadaf Ebrahimi 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85,
735*62c56f98SSadaf Ebrahimi 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e,
736*62c56f98SSadaf Ebrahimi 0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15,
737*62c56f98SSadaf Ebrahimi 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45,
738*62c56f98SSadaf Ebrahimi 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8,
739*62c56f98SSadaf Ebrahimi 0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c,
740*62c56f98SSadaf Ebrahimi 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3,
741*62c56f98SSadaf Ebrahimi 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce,
742*62c56f98SSadaf Ebrahimi 0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e,
743*62c56f98SSadaf Ebrahimi 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76,
744*62c56f98SSadaf Ebrahimi 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77,
745*62c56f98SSadaf Ebrahimi 0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe };
746*62c56f98SSadaf Ebrahimi
747*62c56f98SSadaf Ebrahimi static const unsigned char entropy_source_nopr[] =
748*62c56f98SSadaf Ebrahimi { 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d,
749*62c56f98SSadaf Ebrahimi 0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0,
750*62c56f98SSadaf Ebrahimi 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73,
751*62c56f98SSadaf Ebrahimi 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c,
752*62c56f98SSadaf Ebrahimi 0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2,
753*62c56f98SSadaf Ebrahimi 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1,
754*62c56f98SSadaf Ebrahimi 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a,
755*62c56f98SSadaf Ebrahimi 0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb,
756*62c56f98SSadaf Ebrahimi 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a,
757*62c56f98SSadaf Ebrahimi 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 };
758*62c56f98SSadaf Ebrahimi
759*62c56f98SSadaf Ebrahimi static const unsigned char pers_pr[] =
760*62c56f98SSadaf Ebrahimi { 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33,
761*62c56f98SSadaf Ebrahimi 0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e,
762*62c56f98SSadaf Ebrahimi 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0,
763*62c56f98SSadaf Ebrahimi 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 };
764*62c56f98SSadaf Ebrahimi
765*62c56f98SSadaf Ebrahimi static const unsigned char pers_nopr[] =
766*62c56f98SSadaf Ebrahimi { 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29,
767*62c56f98SSadaf Ebrahimi 0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf,
768*62c56f98SSadaf Ebrahimi 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb,
769*62c56f98SSadaf Ebrahimi 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b };
770*62c56f98SSadaf Ebrahimi
771*62c56f98SSadaf Ebrahimi static const unsigned char result_pr[] =
772*62c56f98SSadaf Ebrahimi { 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85,
773*62c56f98SSadaf Ebrahimi 0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d,
774*62c56f98SSadaf Ebrahimi 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62,
775*62c56f98SSadaf Ebrahimi 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d,
776*62c56f98SSadaf Ebrahimi 0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb,
777*62c56f98SSadaf Ebrahimi 0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39,
778*62c56f98SSadaf Ebrahimi 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40,
779*62c56f98SSadaf Ebrahimi 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 };
780*62c56f98SSadaf Ebrahimi
781*62c56f98SSadaf Ebrahimi static const unsigned char result_nopr[] =
782*62c56f98SSadaf Ebrahimi { 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad,
783*62c56f98SSadaf Ebrahimi 0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3,
784*62c56f98SSadaf Ebrahimi 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b,
785*62c56f98SSadaf Ebrahimi 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14,
786*62c56f98SSadaf Ebrahimi 0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54,
787*62c56f98SSadaf Ebrahimi 0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30,
788*62c56f98SSadaf Ebrahimi 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a,
789*62c56f98SSadaf Ebrahimi 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 };
790*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
791*62c56f98SSadaf Ebrahimi
792*62c56f98SSadaf Ebrahimi static size_t test_offset;
ctr_drbg_self_test_entropy(void * data,unsigned char * buf,size_t len)793*62c56f98SSadaf Ebrahimi static int ctr_drbg_self_test_entropy(void *data, unsigned char *buf,
794*62c56f98SSadaf Ebrahimi size_t len)
795*62c56f98SSadaf Ebrahimi {
796*62c56f98SSadaf Ebrahimi const unsigned char *p = data;
797*62c56f98SSadaf Ebrahimi memcpy(buf, p + test_offset, len);
798*62c56f98SSadaf Ebrahimi test_offset += len;
799*62c56f98SSadaf Ebrahimi return 0;
800*62c56f98SSadaf Ebrahimi }
801*62c56f98SSadaf Ebrahimi
802*62c56f98SSadaf Ebrahimi #define CHK(c) if ((c) != 0) \
803*62c56f98SSadaf Ebrahimi { \
804*62c56f98SSadaf Ebrahimi if (verbose != 0) \
805*62c56f98SSadaf Ebrahimi mbedtls_printf("failed\n"); \
806*62c56f98SSadaf Ebrahimi return 1; \
807*62c56f98SSadaf Ebrahimi }
808*62c56f98SSadaf Ebrahimi
809*62c56f98SSadaf Ebrahimi #define SELF_TEST_OUTPUT_DISCARD_LENGTH 64
810*62c56f98SSadaf Ebrahimi
811*62c56f98SSadaf Ebrahimi /*
812*62c56f98SSadaf Ebrahimi * Checkup routine
813*62c56f98SSadaf Ebrahimi */
mbedtls_ctr_drbg_self_test(int verbose)814*62c56f98SSadaf Ebrahimi int mbedtls_ctr_drbg_self_test(int verbose)
815*62c56f98SSadaf Ebrahimi {
816*62c56f98SSadaf Ebrahimi mbedtls_ctr_drbg_context ctx;
817*62c56f98SSadaf Ebrahimi unsigned char buf[sizeof(result_pr)];
818*62c56f98SSadaf Ebrahimi
819*62c56f98SSadaf Ebrahimi mbedtls_ctr_drbg_init(&ctx);
820*62c56f98SSadaf Ebrahimi
821*62c56f98SSadaf Ebrahimi /*
822*62c56f98SSadaf Ebrahimi * Based on a NIST CTR_DRBG test vector (PR = True)
823*62c56f98SSadaf Ebrahimi */
824*62c56f98SSadaf Ebrahimi if (verbose != 0) {
825*62c56f98SSadaf Ebrahimi mbedtls_printf(" CTR_DRBG (PR = TRUE) : ");
826*62c56f98SSadaf Ebrahimi }
827*62c56f98SSadaf Ebrahimi
828*62c56f98SSadaf Ebrahimi test_offset = 0;
829*62c56f98SSadaf Ebrahimi mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
830*62c56f98SSadaf Ebrahimi mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2);
831*62c56f98SSadaf Ebrahimi CHK(mbedtls_ctr_drbg_seed(&ctx,
832*62c56f98SSadaf Ebrahimi ctr_drbg_self_test_entropy,
833*62c56f98SSadaf Ebrahimi (void *) entropy_source_pr,
834*62c56f98SSadaf Ebrahimi pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE));
835*62c56f98SSadaf Ebrahimi mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_ON);
836*62c56f98SSadaf Ebrahimi CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH));
837*62c56f98SSadaf Ebrahimi CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_pr)));
838*62c56f98SSadaf Ebrahimi CHK(memcmp(buf, result_pr, sizeof(result_pr)));
839*62c56f98SSadaf Ebrahimi
840*62c56f98SSadaf Ebrahimi mbedtls_ctr_drbg_free(&ctx);
841*62c56f98SSadaf Ebrahimi
842*62c56f98SSadaf Ebrahimi if (verbose != 0) {
843*62c56f98SSadaf Ebrahimi mbedtls_printf("passed\n");
844*62c56f98SSadaf Ebrahimi }
845*62c56f98SSadaf Ebrahimi
846*62c56f98SSadaf Ebrahimi /*
847*62c56f98SSadaf Ebrahimi * Based on a NIST CTR_DRBG test vector (PR = FALSE)
848*62c56f98SSadaf Ebrahimi */
849*62c56f98SSadaf Ebrahimi if (verbose != 0) {
850*62c56f98SSadaf Ebrahimi mbedtls_printf(" CTR_DRBG (PR = FALSE): ");
851*62c56f98SSadaf Ebrahimi }
852*62c56f98SSadaf Ebrahimi
853*62c56f98SSadaf Ebrahimi mbedtls_ctr_drbg_init(&ctx);
854*62c56f98SSadaf Ebrahimi
855*62c56f98SSadaf Ebrahimi test_offset = 0;
856*62c56f98SSadaf Ebrahimi mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
857*62c56f98SSadaf Ebrahimi mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2);
858*62c56f98SSadaf Ebrahimi CHK(mbedtls_ctr_drbg_seed(&ctx,
859*62c56f98SSadaf Ebrahimi ctr_drbg_self_test_entropy,
860*62c56f98SSadaf Ebrahimi (void *) entropy_source_nopr,
861*62c56f98SSadaf Ebrahimi pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE));
862*62c56f98SSadaf Ebrahimi CHK(mbedtls_ctr_drbg_reseed(&ctx, NULL, 0));
863*62c56f98SSadaf Ebrahimi CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH));
864*62c56f98SSadaf Ebrahimi CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_nopr)));
865*62c56f98SSadaf Ebrahimi CHK(memcmp(buf, result_nopr, sizeof(result_nopr)));
866*62c56f98SSadaf Ebrahimi
867*62c56f98SSadaf Ebrahimi mbedtls_ctr_drbg_free(&ctx);
868*62c56f98SSadaf Ebrahimi
869*62c56f98SSadaf Ebrahimi if (verbose != 0) {
870*62c56f98SSadaf Ebrahimi mbedtls_printf("passed\n");
871*62c56f98SSadaf Ebrahimi }
872*62c56f98SSadaf Ebrahimi
873*62c56f98SSadaf Ebrahimi if (verbose != 0) {
874*62c56f98SSadaf Ebrahimi mbedtls_printf("\n");
875*62c56f98SSadaf Ebrahimi }
876*62c56f98SSadaf Ebrahimi
877*62c56f98SSadaf Ebrahimi return 0;
878*62c56f98SSadaf Ebrahimi }
879*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_SELF_TEST */
880*62c56f98SSadaf Ebrahimi
881*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_CTR_DRBG_C */
882