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