Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/mbedtls/library/ctr_drbg.c
9903 views
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
{
75
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
mbedtls_aes_init(&ctx->aes_ctx);
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
*/
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_CTR_DRBG_USE_PSA_CRYPTO)
106
ctr_drbg_destroy_psa_contex(&ctx->psa_ctx);
107
#else
108
mbedtls_aes_free(&ctx->aes_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
115
void mbedtls_ctr_drbg_set_prediction_resistance(mbedtls_ctr_drbg_context *ctx,
116
int resistance)
117
{
118
ctx->prediction_resistance = resistance;
119
}
120
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
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
155
void mbedtls_ctr_drbg_set_reseed_interval(mbedtls_ctr_drbg_context *ctx,
156
int interval)
157
{
158
ctx->reseed_interval = interval;
159
}
160
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_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
mbedtls_aes_context aes_ctx;
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_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
mbedtls_aes_init(&aes_ctx);
220
221
if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, key,
222
MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
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_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
if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,
250
chain, chain)) != 0) {
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_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
if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, tmp,
277
MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
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_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
if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,
294
iv, iv)) != 0) {
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_CTR_DRBG_USE_PSA_CRYPTO)
303
ctr_drbg_destroy_psa_contex(&psa_ctx);
304
#else
305
mbedtls_aes_free(&aes_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
*/
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_CTR_DRBG_USE_PSA_CRYPTO)
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_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
if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
364
ctx->counter, p)) != 0) {
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_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
if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, tmp,
387
MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
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
*/
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
*/
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
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. */
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
*/
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_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
if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, key,
577
MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
578
return ret;
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
*/
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_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
if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
670
ctx->counter, locals.tmp)) != 0) {
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
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)
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
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;
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
*/
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
1018