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