Coverage Report

Created: 2026-05-12 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/mbedtls/library/ctr_drbg.c
Line
Count
Source
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_CTR_DRBG_USE_PSA_CRYPTO)
30
#include "psa_util_internal.h"
31
#endif
32
33
#include "mbedtls/platform.h"
34
35
#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
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
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
 */
73
void mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context *ctx)
74
13.1k
{
75
13.1k
    memset(ctx, 0, sizeof(mbedtls_ctr_drbg_context));
76
#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
77
    ctx->psa_ctx.key_id = MBEDTLS_SVC_KEY_ID_INIT;
78
    ctx->psa_ctx.operation = psa_cipher_operation_init();
79
#else
80
13.1k
    mbedtls_aes_init(&ctx->aes_ctx);
81
13.1k
#endif
82
    /* Indicate that the entropy nonce length is not set explicitly.
83
     * See mbedtls_ctr_drbg_set_nonce_len(). */
84
13.1k
    ctx->reseed_counter = -1;
85
86
13.1k
    ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
87
13.1k
}
88
89
/*
90
 *  This function resets CTR_DRBG context to the state immediately
91
 *  after initial call of mbedtls_ctr_drbg_init().
92
 */
93
void mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context *ctx)
94
13.1k
{
95
13.1k
    if (ctx == NULL) {
96
0
        return;
97
0
    }
98
99
13.1k
#if defined(MBEDTLS_THREADING_C)
100
    /* The mutex is initialized iff f_entropy is set. */
101
13.1k
    if (ctx->f_entropy != NULL) {
102
13.0k
        mbedtls_mutex_free(&ctx->mutex);
103
13.0k
    }
104
13.1k
#endif
105
#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
106
    ctr_drbg_destroy_psa_contex(&ctx->psa_ctx);
107
#else
108
13.1k
    mbedtls_aes_free(&ctx->aes_ctx);
109
13.1k
#endif
110
13.1k
    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ctr_drbg_context));
111
13.1k
    ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
112
13.1k
    ctx->reseed_counter = -1;
113
13.1k
}
114
115
void mbedtls_ctr_drbg_set_prediction_resistance(mbedtls_ctr_drbg_context *ctx,
116
                                                int resistance)
117
0
{
118
0
    ctx->prediction_resistance = resistance;
119
0
}
120
121
void mbedtls_ctr_drbg_set_entropy_len(mbedtls_ctr_drbg_context *ctx,
122
                                      size_t len)
123
0
{
124
0
    ctx->entropy_len = len;
125
0
}
126
127
int mbedtls_ctr_drbg_set_nonce_len(mbedtls_ctr_drbg_context *ctx,
128
                                   size_t len)
129
0
{
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
0
    if (ctx->f_entropy != NULL) {
133
0
        return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
134
0
    }
135
136
0
    if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
137
0
        return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
138
0
    }
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
0
    if (len > INT_MAX) {
144
0
        return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
145
0
    }
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
0
    ctx->reseed_counter = (int) len;
152
0
    return 0;
153
0
}
154
155
void mbedtls_ctr_drbg_set_reseed_interval(mbedtls_ctr_drbg_context *ctx,
156
                                          int interval)
157
0
{
158
0
    ctx->reseed_interval = interval;
159
0
}
160
161
static int block_cipher_df(unsigned char *output,
162
                           const unsigned char *data, size_t data_len)
163
12.9k
{
164
12.9k
    unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
165
12.9k
                      MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
166
12.9k
    unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
167
12.9k
    unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
168
12.9k
    unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
169
12.9k
    unsigned char *p, *iv;
170
12.9k
    int ret = 0;
171
#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
172
    psa_status_t status;
173
    size_t tmp_len;
174
    mbedtls_ctr_drbg_psa_context psa_ctx;
175
176
    psa_ctx.key_id = MBEDTLS_SVC_KEY_ID_INIT;
177
    psa_ctx.operation = psa_cipher_operation_init();
178
#else
179
12.9k
    mbedtls_aes_context aes_ctx;
180
12.9k
#endif
181
182
12.9k
    int i, j;
183
12.9k
    size_t buf_len, use_len;
184
185
12.9k
    if (data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
186
0
        return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
187
0
    }
188
189
12.9k
    memset(buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
190
12.9k
           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
12.9k
    p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
200
12.9k
    MBEDTLS_PUT_UINT32_BE(data_len, p, 0);
201
12.9k
    p += 4 + 3;
202
12.9k
    *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
203
12.9k
    memcpy(p, data, data_len);
204
12.9k
    p[data_len] = 0x80;
205
206
12.9k
    buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
207
208
428k
    for (i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++) {
209
415k
        key[i] = i;
210
415k
    }
211
212
#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
213
    status = ctr_drbg_setup_psa_context(&psa_ctx, key, sizeof(key));
214
    if (status != PSA_SUCCESS) {
215
        ret = psa_generic_status_to_mbedtls(status);
216
        goto exit;
217
    }
218
#else
219
12.9k
    mbedtls_aes_init(&aes_ctx);
220
221
12.9k
    if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, key,
222
12.9k
                                      MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
223
0
        goto exit;
224
0
    }
225
12.9k
#endif
226
227
    /*
228
     * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
229
     */
230
51.9k
    for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
231
38.9k
        p = buf;
232
38.9k
        memset(chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE);
233
38.9k
        use_len = buf_len;
234
235
272k
        while (use_len > 0) {
236
233k
            mbedtls_xor(chain, chain, p, MBEDTLS_CTR_DRBG_BLOCKSIZE);
237
233k
            p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
238
233k
            use_len -= (use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE) ?
239
194k
                       MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
240
241
#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
242
            status = psa_cipher_update(&psa_ctx.operation, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE,
243
                                       chain, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);
244
            if (status != PSA_SUCCESS) {
245
                ret = psa_generic_status_to_mbedtls(status);
246
                goto exit;
247
            }
248
#else
249
233k
            if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,
250
233k
                                             chain, chain)) != 0) {
251
0
                goto exit;
252
0
            }
253
233k
#endif
254
233k
        }
255
256
38.9k
        memcpy(tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE);
257
258
        /*
259
         * Update IV
260
         */
261
38.9k
        buf[3]++;
262
38.9k
    }
263
264
    /*
265
     * Do final encryption with reduced data
266
     */
267
#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
268
    ctr_drbg_destroy_psa_contex(&psa_ctx);
269
270
    status = ctr_drbg_setup_psa_context(&psa_ctx, tmp, MBEDTLS_CTR_DRBG_KEYSIZE);
271
    if (status != PSA_SUCCESS) {
272
        ret = psa_generic_status_to_mbedtls(status);
273
        goto exit;
274
    }
275
#else
276
12.9k
    if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, tmp,
277
12.9k
                                      MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
278
0
        goto exit;
279
0
    }
280
12.9k
#endif
281
12.9k
    iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
282
12.9k
    p = output;
283
284
51.9k
    for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
285
#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
286
        status = psa_cipher_update(&psa_ctx.operation, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE,
287
                                   iv, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);
288
        if (status != PSA_SUCCESS) {
289
            ret = psa_generic_status_to_mbedtls(status);
290
            goto exit;
291
        }
292
#else
293
38.9k
        if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,
294
38.9k
                                         iv, iv)) != 0) {
295
0
            goto exit;
296
0
        }
297
38.9k
#endif
298
38.9k
        memcpy(p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE);
299
38.9k
        p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
300
38.9k
    }
301
12.9k
exit:
302
#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
303
    ctr_drbg_destroy_psa_contex(&psa_ctx);
304
#else
305
12.9k
    mbedtls_aes_free(&aes_ctx);
306
12.9k
#endif
307
    /*
308
     * tidy up the stack
309
     */
310
12.9k
    mbedtls_platform_zeroize(buf, sizeof(buf));
311
12.9k
    mbedtls_platform_zeroize(tmp, sizeof(tmp));
312
12.9k
    mbedtls_platform_zeroize(key, sizeof(key));
313
12.9k
    mbedtls_platform_zeroize(chain, sizeof(chain));
314
12.9k
    if (0 != ret) {
315
        /*
316
         * wipe partial seed from memory
317
         */
318
0
        mbedtls_platform_zeroize(output, MBEDTLS_CTR_DRBG_SEEDLEN);
319
0
    }
320
321
12.9k
    return ret;
322
12.9k
}
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
 */
332
static int ctr_drbg_update_internal(mbedtls_ctr_drbg_context *ctx,
333
                                    const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN])
334
72.4k
{
335
72.4k
    unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
336
72.4k
    unsigned char *p = tmp;
337
72.4k
    int j;
338
72.4k
    int ret = 0;
339
#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
340
    psa_status_t status;
341
    size_t tmp_len;
342
#endif
343
344
72.4k
    memset(tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN);
345
346
289k
    for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
347
        /*
348
         * Increase counter
349
         */
350
217k
        mbedtls_ctr_increment_counter(ctx->counter);
351
352
        /*
353
         * Crypt counter block
354
         */
355
#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
356
        status = psa_cipher_update(&ctx->psa_ctx.operation, ctx->counter, sizeof(ctx->counter),
357
                                   p, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);
358
        if (status != PSA_SUCCESS) {
359
            ret = psa_generic_status_to_mbedtls(status);
360
            goto exit;
361
        }
362
#else
363
217k
        if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
364
217k
                                         ctx->counter, p)) != 0) {
365
0
            goto exit;
366
0
        }
367
217k
#endif
368
369
217k
        p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
370
217k
    }
371
372
72.4k
    mbedtls_xor(tmp, tmp, data, MBEDTLS_CTR_DRBG_SEEDLEN);
373
374
    /*
375
     * Update key and counter
376
     */
377
#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
378
    ctr_drbg_destroy_psa_contex(&ctx->psa_ctx);
379
380
    status = ctr_drbg_setup_psa_context(&ctx->psa_ctx, tmp, MBEDTLS_CTR_DRBG_KEYSIZE);
381
    if (status != PSA_SUCCESS) {
382
        ret = psa_generic_status_to_mbedtls(status);
383
        goto exit;
384
    }
385
#else
386
72.4k
    if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, tmp,
387
72.4k
                                      MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
388
0
        goto exit;
389
0
    }
390
72.4k
#endif
391
72.4k
    memcpy(ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
392
72.4k
           MBEDTLS_CTR_DRBG_BLOCKSIZE);
393
394
72.4k
exit:
395
72.4k
    mbedtls_platform_zeroize(tmp, sizeof(tmp));
396
72.4k
    return ret;
397
72.4k
}
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
 */
411
int mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context *ctx,
412
                            const unsigned char *additional,
413
                            size_t add_len)
414
0
{
415
0
    unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
416
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
417
418
0
    if (add_len == 0) {
419
0
        return 0;
420
0
    }
421
422
0
    if ((ret = block_cipher_df(add_input, additional, add_len)) != 0) {
423
0
        goto exit;
424
0
    }
425
0
    if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {
426
0
        goto exit;
427
0
    }
428
429
0
exit:
430
0
    mbedtls_platform_zeroize(add_input, sizeof(add_input));
431
0
    return ret;
432
0
}
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
 */
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
13.0k
{
452
13.0k
    unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
453
13.0k
    size_t seedlen = 0;
454
13.0k
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
455
456
13.0k
    if (ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
457
0
        return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
458
0
    }
459
13.0k
    if (nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len) {
460
0
        return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
461
0
    }
462
13.0k
    if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len) {
463
0
        return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
464
0
    }
465
466
13.0k
    memset(seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT);
467
468
    /* Gather entropy_len bytes of entropy to seed state. */
469
13.0k
    if (0 != ctx->f_entropy(ctx->p_entropy, seed, ctx->entropy_len)) {
470
101
        return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
471
101
    }
472
12.9k
    seedlen += ctx->entropy_len;
473
474
    /* Gather entropy for a nonce if requested. */
475
12.9k
    if (nonce_len != 0) {
476
0
        if (0 != ctx->f_entropy(ctx->p_entropy, seed + seedlen, nonce_len)) {
477
0
            return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
478
0
        }
479
0
        seedlen += nonce_len;
480
0
    }
481
482
    /* Add additional data if provided. */
483
12.9k
    if (additional != NULL && len != 0) {
484
12.9k
        memcpy(seed + seedlen, additional, len);
485
12.9k
        seedlen += len;
486
12.9k
    }
487
488
    /* Reduce to 384 bits. */
489
12.9k
    if ((ret = block_cipher_df(seed, seed, seedlen)) != 0) {
490
0
        goto exit;
491
0
    }
492
493
    /* Update state. */
494
12.9k
    if ((ret = ctr_drbg_update_internal(ctx, seed)) != 0) {
495
0
        goto exit;
496
0
    }
497
12.9k
    ctx->reseed_counter = 0;
498
499
12.9k
exit:
500
12.9k
    mbedtls_platform_zeroize(seed, sizeof(seed));
501
12.9k
    return ret;
502
12.9k
}
503
504
int mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context *ctx,
505
                            const unsigned char *additional, size_t len)
506
0
{
507
0
    return mbedtls_ctr_drbg_reseed_internal(ctx, additional, len, 0);
508
0
}
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. */
515
static size_t good_nonce_len(size_t entropy_len)
516
13.0k
{
517
13.0k
    if (entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2) {
518
13.0k
        return 0;
519
13.0k
    } else {
520
0
        return (entropy_len + 1) / 2;
521
0
    }
522
13.0k
}
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
 */
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
13.0k
{
541
13.0k
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
542
13.0k
    unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
543
13.0k
    size_t nonce_len;
544
545
13.0k
    memset(key, 0, MBEDTLS_CTR_DRBG_KEYSIZE);
546
547
    /* The mutex is initialized iff f_entropy is set. */
548
13.0k
#if defined(MBEDTLS_THREADING_C)
549
13.0k
    mbedtls_mutex_init(&ctx->mutex);
550
13.0k
#endif
551
552
13.0k
    ctx->f_entropy = f_entropy;
553
13.0k
    ctx->p_entropy = p_entropy;
554
555
13.0k
    if (ctx->entropy_len == 0) {
556
13.0k
        ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
557
13.0k
    }
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
13.0k
    nonce_len = (ctx->reseed_counter >= 0 ?
563
0
                 (size_t) ctx->reseed_counter :
564
13.0k
                 good_nonce_len(ctx->entropy_len));
565
566
    /* Initialize with an empty key. */
567
#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
568
    psa_status_t status;
569
570
    status = ctr_drbg_setup_psa_context(&ctx->psa_ctx, key, MBEDTLS_CTR_DRBG_KEYSIZE);
571
    if (status != PSA_SUCCESS) {
572
        ret = psa_generic_status_to_mbedtls(status);
573
        return status;
574
    }
575
#else
576
13.0k
    if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, key,
577
13.0k
                                      MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
578
0
        return ret;
579
0
    }
580
13.0k
#endif
581
582
    /* Do the initial seeding. */
583
13.0k
    if ((ret = mbedtls_ctr_drbg_reseed_internal(ctx, custom, len,
584
13.0k
                                                nonce_len)) != 0) {
585
101
        return ret;
586
101
    }
587
12.9k
    return 0;
588
13.0k
}
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
 */
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
59.4k
{
613
59.4k
    int ret = 0;
614
59.4k
    mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
615
59.4k
    unsigned char *p = output;
616
59.4k
    struct {
617
59.4k
        unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
618
59.4k
        unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
619
59.4k
    } locals;
620
59.4k
    size_t use_len;
621
622
59.4k
    if (output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST) {
623
0
        return MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG;
624
0
    }
625
626
59.4k
    if (add_len > MBEDTLS_CTR_DRBG_MAX_INPUT) {
627
0
        return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
628
0
    }
629
630
59.4k
    memset(locals.add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN);
631
632
59.4k
    if (ctx->reseed_counter >= ctx->reseed_interval ||
633
59.4k
        ctx->prediction_resistance) {
634
0
        if ((ret = mbedtls_ctr_drbg_reseed(ctx, additional, add_len)) != 0) {
635
0
            return ret;
636
0
        }
637
0
        add_len = 0;
638
0
    }
639
640
59.4k
    if (add_len > 0) {
641
0
        if ((ret = block_cipher_df(locals.add_input, additional, add_len)) != 0) {
642
0
            goto exit;
643
0
        }
644
0
        if ((ret = ctr_drbg_update_internal(ctx, locals.add_input)) != 0) {
645
0
            goto exit;
646
0
        }
647
0
    }
648
649
134k
    while (output_len > 0) {
650
        /*
651
         * Increase counter (treat it as a 128-bit big-endian integer).
652
         */
653
75.2k
        mbedtls_ctr_increment_counter(ctx->counter);
654
655
        /*
656
         * Crypt counter block
657
         */
658
#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
659
        psa_status_t status;
660
        size_t tmp_len;
661
662
        status = psa_cipher_update(&ctx->psa_ctx.operation, ctx->counter, sizeof(ctx->counter),
663
                                   locals.tmp, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);
664
        if (status != PSA_SUCCESS) {
665
            ret = psa_generic_status_to_mbedtls(status);
666
            goto exit;
667
        }
668
#else
669
75.2k
        if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
670
75.2k
                                         ctx->counter, locals.tmp)) != 0) {
671
0
            goto exit;
672
0
        }
673
75.2k
#endif
674
675
75.2k
        use_len = (output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE)
676
75.2k
            ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
677
        /*
678
         * Copy random block to destination
679
         */
680
75.2k
        memcpy(p, locals.tmp, use_len);
681
75.2k
        p += use_len;
682
75.2k
        output_len -= use_len;
683
75.2k
    }
684
685
59.4k
    if ((ret = ctr_drbg_update_internal(ctx, locals.add_input)) != 0) {
686
0
        goto exit;
687
0
    }
688
689
59.4k
    ctx->reseed_counter++;
690
691
59.4k
exit:
692
59.4k
    mbedtls_platform_zeroize(&locals, sizeof(locals));
693
59.4k
    return ret;
694
59.4k
}
695
696
int mbedtls_ctr_drbg_random(void *p_rng, unsigned char *output,
697
                            size_t output_len)
698
59.4k
{
699
59.4k
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
700
59.4k
    mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
701
702
59.4k
#if defined(MBEDTLS_THREADING_C)
703
59.4k
    if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
704
0
        return ret;
705
0
    }
706
59.4k
#endif
707
708
59.4k
    ret = mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, NULL, 0);
709
710
59.4k
#if defined(MBEDTLS_THREADING_C)
711
59.4k
    if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
712
0
        return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
713
0
    }
714
59.4k
#endif
715
716
59.4k
    return ret;
717
59.4k
}
718
719
#if defined(MBEDTLS_FS_IO)
720
int mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context *ctx,
721
                                     const char *path)
722
0
{
723
0
    int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
724
0
    FILE *f;
725
0
    unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT];
726
727
0
    if ((f = fopen(path, "wb")) == NULL) {
728
0
        return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
729
0
    }
730
731
    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
732
0
    mbedtls_setbuf(f, NULL);
733
734
0
    if ((ret = mbedtls_ctr_drbg_random(ctx, buf,
735
0
                                       MBEDTLS_CTR_DRBG_MAX_INPUT)) != 0) {
736
0
        goto exit;
737
0
    }
738
739
0
    if (fwrite(buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f) !=
740
0
        MBEDTLS_CTR_DRBG_MAX_INPUT) {
741
0
        ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
742
0
    } else {
743
0
        ret = 0;
744
0
    }
745
746
0
exit:
747
0
    mbedtls_platform_zeroize(buf, sizeof(buf));
748
749
0
    fclose(f);
750
0
    return ret;
751
0
}
752
753
int mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context *ctx,
754
                                      const char *path)
755
0
{
756
0
    int ret = 0;
757
0
    FILE *f = NULL;
758
0
    size_t n;
759
0
    unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT];
760
0
    unsigned char c;
761
762
0
    if ((f = fopen(path, "rb")) == NULL) {
763
0
        return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
764
0
    }
765
766
    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
767
0
    mbedtls_setbuf(f, NULL);
768
769
0
    n = fread(buf, 1, sizeof(buf), f);
770
0
    if (fread(&c, 1, 1, f) != 0) {
771
0
        ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
772
0
        goto exit;
773
0
    }
774
0
    if (n == 0 || ferror(f)) {
775
0
        ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
776
0
        goto exit;
777
0
    }
778
0
    fclose(f);
779
0
    f = NULL;
780
781
0
    ret = mbedtls_ctr_drbg_update(ctx, buf, n);
782
783
0
exit:
784
0
    mbedtls_platform_zeroize(buf, sizeof(buf));
785
0
    if (f != NULL) {
786
0
        fclose(f);
787
0
    }
788
0
    if (ret != 0) {
789
0
        return ret;
790
0
    }
791
0
    return mbedtls_ctr_drbg_write_seed_file(ctx, path);
792
0
}
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;
928
static int ctr_drbg_self_test_entropy(void *data, unsigned char *buf,
929
                                      size_t len)
930
0
{
931
0
    const unsigned char *p = data;
932
0
    memcpy(buf, p + test_offset, len);
933
0
    test_offset += len;
934
0
    return 0;
935
0
}
936
937
0
#define CHK(c)    if ((c) != 0)                          \
938
0
    {                                       \
939
0
        if (verbose != 0)                  \
940
0
        mbedtls_printf("failed\n");  \
941
0
        return 1;                        \
942
0
    }
943
944
#define SELF_TEST_OUTPUT_DISCARD_LENGTH 64
945
946
/*
947
 * Checkup routine
948
 */
949
int mbedtls_ctr_drbg_self_test(int verbose)
950
0
{
951
0
    mbedtls_ctr_drbg_context ctx;
952
0
    unsigned char buf[sizeof(result_pr)];
953
954
0
    mbedtls_ctr_drbg_init(&ctx);
955
956
    /*
957
     * Based on a NIST CTR_DRBG test vector (PR = True)
958
     */
959
0
    if (verbose != 0) {
960
0
        mbedtls_printf("  CTR_DRBG (PR = TRUE) : ");
961
0
    }
962
963
0
    test_offset = 0;
964
0
    mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
965
0
    mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2);
966
0
    CHK(mbedtls_ctr_drbg_seed(&ctx,
967
0
                              ctr_drbg_self_test_entropy,
968
0
                              (void *) entropy_source_pr,
969
0
                              pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE));
970
0
    mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_ON);
971
0
    CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH));
972
0
    CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_pr)));
973
0
    CHK(memcmp(buf, result_pr, sizeof(result_pr)));
974
975
0
    mbedtls_ctr_drbg_free(&ctx);
976
977
0
    if (verbose != 0) {
978
0
        mbedtls_printf("passed\n");
979
0
    }
980
981
    /*
982
     * Based on a NIST CTR_DRBG test vector (PR = FALSE)
983
     */
984
0
    if (verbose != 0) {
985
0
        mbedtls_printf("  CTR_DRBG (PR = FALSE): ");
986
0
    }
987
988
0
    mbedtls_ctr_drbg_init(&ctx);
989
990
0
    test_offset = 0;
991
0
    mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
992
0
    mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2);
993
0
    CHK(mbedtls_ctr_drbg_seed(&ctx,
994
0
                              ctr_drbg_self_test_entropy,
995
0
                              (void *) entropy_source_nopr,
996
0
                              pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE));
997
0
    CHK(mbedtls_ctr_drbg_reseed(&ctx, NULL, 0));
998
0
    CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH));
999
0
    CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_nopr)));
1000
0
    CHK(memcmp(buf, result_nopr, sizeof(result_nopr)));
1001
1002
0
    mbedtls_ctr_drbg_free(&ctx);
1003
1004
0
    if (verbose != 0) {
1005
0
        mbedtls_printf("passed\n");
1006
0
    }
1007
1008
0
    if (verbose != 0) {
1009
0
        mbedtls_printf("\n");
1010
0
    }
1011
1012
0
    return 0;
1013
0
}
1014
#endif /* MBEDTLS_SELF_TEST */
1015
1016
#endif /* MBEDTLS_CTR_DRBG_C */