blob: f9bdcc425849ed3339b5e35f3ee4a7ba2967b7e4 [file] [log] [blame]
Edison Aic6672fd2018-02-28 15:01:47 +08001// SPDX-License-Identifier: Apache-2.0
Jens Wiklander817466c2018-05-22 13:49:31 +02002/*
3 * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
4 *
5 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Jens Wiklander817466c2018-05-22 13:49:31 +02006 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 * This file is part of mbed TLS (https://tls.mbed.org)
20 */
21/*
Jens Wiklander3d3b0592019-03-20 15:30:29 +010022 * The NIST SP 800-90 DRBGs are described in the following publication.
Jens Wiklander817466c2018-05-22 13:49:31 +020023 *
24 * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
25 */
26
27#if !defined(MBEDTLS_CONFIG_FILE)
28#include "mbedtls/config.h"
29#else
30#include MBEDTLS_CONFIG_FILE
31#endif
32
33#if defined(MBEDTLS_CTR_DRBG_C)
34
35#include "mbedtls/ctr_drbg.h"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010036#include "mbedtls/platform_util.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020037
38#include <string.h>
39
40#if defined(MBEDTLS_FS_IO)
41#include <stdio.h>
42#endif
43
44#if defined(MBEDTLS_SELF_TEST)
45#if defined(MBEDTLS_PLATFORM_C)
46#include "mbedtls/platform.h"
47#else
48#include <stdio.h>
49#define mbedtls_printf printf
50#endif /* MBEDTLS_PLATFORM_C */
51#endif /* MBEDTLS_SELF_TEST */
52
Jens Wiklander817466c2018-05-22 13:49:31 +020053/*
54 * CTR_DRBG context initialization
55 */
56void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
57{
58 memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
59
60#if defined(MBEDTLS_THREADING_C)
61 mbedtls_mutex_init( &ctx->mutex );
62#endif
63}
64
Jens Wiklander817466c2018-05-22 13:49:31 +020065void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
66{
67 if( ctx == NULL )
68 return;
69
70#if defined(MBEDTLS_THREADING_C)
71 mbedtls_mutex_free( &ctx->mutex );
72#endif
73 mbedtls_aes_free( &ctx->aes_ctx );
Jens Wiklander3d3b0592019-03-20 15:30:29 +010074 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Jens Wiklander817466c2018-05-22 13:49:31 +020075}
76
77void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
78{
79 ctx->prediction_resistance = resistance;
80}
81
82void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len )
83{
84 ctx->entropy_len = len;
85}
86
87void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval )
88{
89 ctx->reseed_interval = interval;
90}
91
92static int block_cipher_df( unsigned char *output,
93 const unsigned char *data, size_t data_len )
94{
95 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
96 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
97 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
98 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
99 unsigned char *p, *iv;
100 mbedtls_aes_context aes_ctx;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100101 int ret = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200102
103 int i, j;
104 size_t buf_len, use_len;
105
106 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
107 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
108
109 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
110 mbedtls_aes_init( &aes_ctx );
111
112 /*
113 * Construct IV (16 bytes) and S in buffer
114 * IV = Counter (in 32-bits) padded to 16 with zeroes
115 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
116 * data || 0x80
117 * (Total is padded to a multiple of 16-bytes with zeroes)
118 */
119 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
120 *p++ = ( data_len >> 24 ) & 0xff;
121 *p++ = ( data_len >> 16 ) & 0xff;
122 *p++ = ( data_len >> 8 ) & 0xff;
123 *p++ = ( data_len ) & 0xff;
124 p += 3;
125 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
126 memcpy( p, data, data_len );
127 p[data_len] = 0x80;
128
129 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
130
131 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
132 key[i] = i;
133
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100134 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
135 {
136 goto exit;
137 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200138
139 /*
140 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
141 */
142 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
143 {
144 p = buf;
145 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
146 use_len = buf_len;
147
148 while( use_len > 0 )
149 {
150 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
151 chain[i] ^= p[i];
152 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
153 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
154 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
155
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100156 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ) ) != 0 )
157 {
158 goto exit;
159 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200160 }
161
162 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
163
164 /*
165 * Update IV
166 */
167 buf[3]++;
168 }
169
170 /*
171 * Do final encryption with reduced data
172 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100173 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
174 {
175 goto exit;
176 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200177 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
178 p = output;
179
180 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
181 {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100182 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) ) != 0 )
183 {
184 goto exit;
185 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200186 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
187 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
188 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100189exit:
Jens Wiklander817466c2018-05-22 13:49:31 +0200190 mbedtls_aes_free( &aes_ctx );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100191 /*
192 * tidy up the stack
193 */
194 mbedtls_platform_zeroize( buf, sizeof( buf ) );
195 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
196 mbedtls_platform_zeroize( key, sizeof( key ) );
197 mbedtls_platform_zeroize( chain, sizeof( chain ) );
198 if( 0 != ret )
199 {
200 /*
201 * wipe partial seed from memory
202 */
203 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
204 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200205
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100206 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200207}
208
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100209/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
210 * ctr_drbg_update_internal(ctx, provided_data)
211 * implements
212 * CTR_DRBG_Update(provided_data, Key, V)
213 * with inputs and outputs
214 * ctx->aes_ctx = Key
215 * ctx->counter = V
216 */
Jens Wiklander817466c2018-05-22 13:49:31 +0200217static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
218 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
219{
220 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
221 unsigned char *p = tmp;
222 int i, j;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100223 int ret = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200224
225 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
226
227 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
228 {
229 /*
230 * Increase counter
231 */
232 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
233 if( ++ctx->counter[i - 1] != 0 )
234 break;
235
236 /*
237 * Crypt counter block
238 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100239 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 )
240 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200241
242 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
243 }
244
245 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
246 tmp[i] ^= data[i];
247
248 /*
249 * Update key and counter
250 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100251 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
252 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200253 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
254
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100255exit:
256 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
257 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200258}
259
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100260/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
261 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
262 * implements
263 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
264 * security_strength) -> initial_working_state
265 * with inputs
266 * ctx->counter = all-bits-0
267 * ctx->aes_ctx = context from all-bits-0 key
268 * additional[:add_len] = entropy_input || nonce || personalization_string
269 * and with outputs
270 * ctx = initial_working_state
271 */
272int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
273 const unsigned char *additional,
274 size_t add_len )
Jens Wiklander817466c2018-05-22 13:49:31 +0200275{
276 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100277 int ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200278
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100279 if( add_len == 0 )
280 return( 0 );
Jens Wiklander817466c2018-05-22 13:49:31 +0200281
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100282 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
283 goto exit;
284 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
285 goto exit;
286
287exit:
288 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
289 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200290}
291
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100292#if !defined(MBEDTLS_DEPRECATED_REMOVED)
293void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
294 const unsigned char *additional,
295 size_t add_len )
296{
297 /* MAX_INPUT would be more logical here, but we have to match
298 * block_cipher_df()'s limits since we can't propagate errors */
299 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
300 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
301 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
302}
303#endif /* MBEDTLS_DEPRECATED_REMOVED */
304
305/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
306 * mbedtls_ctr_drbg_reseed(ctx, additional, len)
307 * implements
308 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
309 * -> new_working_state
310 * with inputs
311 * ctx contains working_state
312 * additional[:len] = additional_input
313 * and entropy_input comes from calling ctx->f_entropy
314 * and with output
315 * ctx contains new_working_state
316 */
Jens Wiklander817466c2018-05-22 13:49:31 +0200317int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
318 const unsigned char *additional, size_t len )
319{
320 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
321 size_t seedlen = 0;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100322 int ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200323
324 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
325 len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
326 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
327
328 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
329
330 /*
331 * Gather entropy_len bytes of entropy to seed state
332 */
333 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
334 ctx->entropy_len ) )
335 {
336 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
337 }
338
339 seedlen += ctx->entropy_len;
340
341 /*
342 * Add additional data
343 */
344 if( additional && len )
345 {
346 memcpy( seed + seedlen, additional, len );
347 seedlen += len;
348 }
349
350 /*
351 * Reduce to 384 bits
352 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100353 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
354 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200355
356 /*
357 * Update state
358 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100359 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
360 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200361 ctx->reseed_counter = 1;
362
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100363exit:
364 mbedtls_platform_zeroize( seed, sizeof( seed ) );
365 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200366}
367
Jerome Forissier5b25c762020-04-07 11:18:49 +0200368/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
369 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
370 * implements
371 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
372 * security_strength) -> initial_working_state
373 * with inputs
374 * custom[:len] = nonce || personalization_string
375 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
376 * and with outputs
377 * ctx = initial_working_state
378 */
379int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
380 int (*f_entropy)(void *, unsigned char *, size_t),
381 void *p_entropy,
382 const unsigned char *custom,
383 size_t len )
384{
385 int ret;
386 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
387
388 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
389
390 mbedtls_aes_init( &ctx->aes_ctx );
391
392 ctx->f_entropy = f_entropy;
393 ctx->p_entropy = p_entropy;
394
395 if( ctx->entropy_len == 0 )
396 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
397 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
398
399 /*
400 * Initialize with an empty key
401 */
402 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
403 {
404 return( ret );
405 }
406
407 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
408 {
409 return( ret );
410 }
411 return( 0 );
412}
413
414/* Backward compatibility wrapper */
415int mbedtls_ctr_drbg_seed_entropy_len(
416 mbedtls_ctr_drbg_context *ctx,
417 int (*f_entropy)(void *, unsigned char *, size_t), void *p_entropy,
418 const unsigned char *custom, size_t len,
419 size_t entropy_len )
420{
421 mbedtls_ctr_drbg_set_entropy_len( ctx, entropy_len );
422 return( mbedtls_ctr_drbg_seed( ctx, f_entropy, p_entropy, custom, len ) );
423}
424
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100425/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
426 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
427 * implements
428 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
429 * -> working_state_after_reseed
430 * if required, then
431 * CTR_DRBG_Generate(working_state_after_reseed,
432 * requested_number_of_bits, additional_input)
433 * -> status, returned_bits, new_working_state
434 * with inputs
435 * ctx contains working_state
436 * requested_number_of_bits = 8 * output_len
437 * additional[:add_len] = additional_input
438 * and entropy_input comes from calling ctx->f_entropy
439 * and with outputs
440 * status = SUCCESS (this function does the reseed internally)
441 * returned_bits = output[:output_len]
442 * ctx contains new_working_state
443 */
Jens Wiklander817466c2018-05-22 13:49:31 +0200444int mbedtls_ctr_drbg_random_with_add( void *p_rng,
445 unsigned char *output, size_t output_len,
446 const unsigned char *additional, size_t add_len )
447{
448 int ret = 0;
449 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
450 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
451 unsigned char *p = output;
452 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
453 int i;
454 size_t use_len;
455
456 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
457 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
458
459 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
460 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
461
462 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
463
464 if( ctx->reseed_counter > ctx->reseed_interval ||
465 ctx->prediction_resistance )
466 {
467 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100468 {
Jens Wiklander817466c2018-05-22 13:49:31 +0200469 return( ret );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100470 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200471 add_len = 0;
472 }
473
474 if( add_len > 0 )
475 {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100476 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
477 goto exit;
478 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
479 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200480 }
481
482 while( output_len > 0 )
483 {
484 /*
485 * Increase counter
486 */
487 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
488 if( ++ctx->counter[i - 1] != 0 )
489 break;
490
491 /*
492 * Crypt counter block
493 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100494 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 )
495 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200496
497 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
498 output_len;
499 /*
500 * Copy random block to destination
501 */
502 memcpy( p, tmp, use_len );
503 p += use_len;
504 output_len -= use_len;
505 }
506
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100507 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
508 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200509
510 ctx->reseed_counter++;
511
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100512exit:
513 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
514 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
Jerome Forissier5b25c762020-04-07 11:18:49 +0200515 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200516}
517
518int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
519{
520 int ret;
521 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
522
523#if defined(MBEDTLS_THREADING_C)
524 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
525 return( ret );
526#endif
527
528 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
529
530#if defined(MBEDTLS_THREADING_C)
531 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
532 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
533#endif
534
535 return( ret );
536}
537
538#if defined(MBEDTLS_FS_IO)
539int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
540{
541 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
542 FILE *f;
543 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
544
545 if( ( f = fopen( path, "wb" ) ) == NULL )
546 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
547
548 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
549 goto exit;
550
551 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
Jens Wiklander817466c2018-05-22 13:49:31 +0200552 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100553 else
554 ret = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200555
556exit:
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100557 mbedtls_platform_zeroize( buf, sizeof( buf ) );
558
Jens Wiklander817466c2018-05-22 13:49:31 +0200559 fclose( f );
560 return( ret );
561}
562
563int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
564{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100565 int ret = 0;
566 FILE *f = NULL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200567 size_t n;
568 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100569 unsigned char c;
Jens Wiklander817466c2018-05-22 13:49:31 +0200570
571 if( ( f = fopen( path, "rb" ) ) == NULL )
572 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
573
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100574 n = fread( buf, 1, sizeof( buf ), f );
575 if( fread( &c, 1, 1, f ) != 0 )
Jens Wiklander817466c2018-05-22 13:49:31 +0200576 {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100577 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
578 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200579 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100580 if( n == 0 || ferror( f ) )
Jens Wiklander817466c2018-05-22 13:49:31 +0200581 {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100582 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
583 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200584 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200585 fclose( f );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100586 f = NULL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200587
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100588 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
Jens Wiklander817466c2018-05-22 13:49:31 +0200589
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100590exit:
591 mbedtls_platform_zeroize( buf, sizeof( buf ) );
592 if( f != NULL )
593 fclose( f );
594 if( ret != 0 )
595 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200596 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
597}
598#endif /* MBEDTLS_FS_IO */
599
600#if defined(MBEDTLS_SELF_TEST)
601
602static const unsigned char entropy_source_pr[96] =
603 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
604 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
605 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
606 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
607 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
608 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
609 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
610 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
611 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
612 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
613 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
614 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
615
616static const unsigned char entropy_source_nopr[64] =
617 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
618 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
619 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
620 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
621 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
622 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
623 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
624 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
625
626static const unsigned char nonce_pers_pr[16] =
627 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
628 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
629
630static const unsigned char nonce_pers_nopr[16] =
631 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
632 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
633
634static const unsigned char result_pr[16] =
635 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
636 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
637
638static const unsigned char result_nopr[16] =
639 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
640 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
641
642static size_t test_offset;
643static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
644 size_t len )
645{
646 const unsigned char *p = data;
647 memcpy( buf, p + test_offset, len );
648 test_offset += len;
649 return( 0 );
650}
651
652#define CHK( c ) if( (c) != 0 ) \
653 { \
654 if( verbose != 0 ) \
655 mbedtls_printf( "failed\n" ); \
656 return( 1 ); \
657 }
658
659/*
660 * Checkup routine
661 */
662int mbedtls_ctr_drbg_self_test( int verbose )
663{
664 mbedtls_ctr_drbg_context ctx;
665 unsigned char buf[16];
666
667 mbedtls_ctr_drbg_init( &ctx );
668
669 /*
670 * Based on a NIST CTR_DRBG test vector (PR = True)
671 */
672 if( verbose != 0 )
673 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
674
675 test_offset = 0;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200676 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
677 CHK( mbedtls_ctr_drbg_seed( &ctx,
678 ctr_drbg_self_test_entropy,
679 (void *) entropy_source_pr,
680 nonce_pers_pr, 16 ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200681 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
682 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
683 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
684 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
685
686 mbedtls_ctr_drbg_free( &ctx );
687
688 if( verbose != 0 )
689 mbedtls_printf( "passed\n" );
690
691 /*
692 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
693 */
694 if( verbose != 0 )
695 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
696
697 mbedtls_ctr_drbg_init( &ctx );
698
699 test_offset = 0;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200700 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
701 CHK( mbedtls_ctr_drbg_seed( &ctx,
702 ctr_drbg_self_test_entropy,
703 (void *) entropy_source_nopr,
704 nonce_pers_nopr, 16 ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200705 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
706 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
707 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
708 CHK( memcmp( buf, result_nopr, 16 ) );
709
710 mbedtls_ctr_drbg_free( &ctx );
711
712 if( verbose != 0 )
713 mbedtls_printf( "passed\n" );
714
715 if( verbose != 0 )
716 mbedtls_printf( "\n" );
717
718 return( 0 );
719}
720#endif /* MBEDTLS_SELF_TEST */
721
722#endif /* MBEDTLS_CTR_DRBG_C */