blob: fb121575bbbe8d737178409175efd5692d1c3278 [file] [log] [blame]
Jens Wiklander817466c2018-05-22 13:49:31 +02001/*
2 * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
3 *
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Jens Wiklander50a57cf2019-03-13 10:41:54 +01005 * SPDX-License-Identifier: Apache-2.0
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 Wiklander50a57cf2019-03-13 10:41:54 +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 Wiklander50a57cf2019-03-13 10:41:54 +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
65/*
66 * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow
67 * NIST tests to succeed (which require known length fixed entropy)
68 */
Jens Wiklander50a57cf2019-03-13 10:41:54 +010069/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
70 * mbedtls_ctr_drbg_seed_entropy_len(ctx, f_entropy, p_entropy,
71 * custom, len, entropy_len)
72 * implements
73 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
74 * security_strength) -> initial_working_state
75 * with inputs
76 * custom[:len] = nonce || personalization_string
77 * where entropy_input comes from f_entropy for entropy_len bytes
78 * and with outputs
79 * ctx = initial_working_state
80 */
Jens Wiklander817466c2018-05-22 13:49:31 +020081int mbedtls_ctr_drbg_seed_entropy_len(
82 mbedtls_ctr_drbg_context *ctx,
83 int (*f_entropy)(void *, unsigned char *, size_t),
84 void *p_entropy,
85 const unsigned char *custom,
86 size_t len,
87 size_t entropy_len )
88{
89 int ret;
90 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
91
92 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
93
94 mbedtls_aes_init( &ctx->aes_ctx );
95
96 ctx->f_entropy = f_entropy;
97 ctx->p_entropy = p_entropy;
98
99 ctx->entropy_len = entropy_len;
100 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
101
102 /*
103 * Initialize with an empty key
104 */
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100105 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
106 {
107 return( ret );
108 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200109
110 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100111 {
Jens Wiklander817466c2018-05-22 13:49:31 +0200112 return( ret );
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100113 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200114 return( 0 );
115}
116
117int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
118 int (*f_entropy)(void *, unsigned char *, size_t),
119 void *p_entropy,
120 const unsigned char *custom,
121 size_t len )
122{
123 return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy, custom, len,
124 MBEDTLS_CTR_DRBG_ENTROPY_LEN ) );
125}
126
127void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
128{
129 if( ctx == NULL )
130 return;
131
132#if defined(MBEDTLS_THREADING_C)
133 mbedtls_mutex_free( &ctx->mutex );
134#endif
135 mbedtls_aes_free( &ctx->aes_ctx );
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100136 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200137}
138
139void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
140{
141 ctx->prediction_resistance = resistance;
142}
143
144void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len )
145{
146 ctx->entropy_len = len;
147}
148
149void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval )
150{
151 ctx->reseed_interval = interval;
152}
153
154static int block_cipher_df( unsigned char *output,
155 const unsigned char *data, size_t data_len )
156{
157 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
158 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
159 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
160 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
161 unsigned char *p, *iv;
162 mbedtls_aes_context aes_ctx;
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100163 int ret = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200164
165 int i, j;
166 size_t buf_len, use_len;
167
168 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
169 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
170
171 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
172 mbedtls_aes_init( &aes_ctx );
173
174 /*
175 * Construct IV (16 bytes) and S in buffer
176 * IV = Counter (in 32-bits) padded to 16 with zeroes
177 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
178 * data || 0x80
179 * (Total is padded to a multiple of 16-bytes with zeroes)
180 */
181 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
182 *p++ = ( data_len >> 24 ) & 0xff;
183 *p++ = ( data_len >> 16 ) & 0xff;
184 *p++ = ( data_len >> 8 ) & 0xff;
185 *p++ = ( data_len ) & 0xff;
186 p += 3;
187 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
188 memcpy( p, data, data_len );
189 p[data_len] = 0x80;
190
191 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
192
193 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
194 key[i] = i;
195
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100196 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
197 {
198 goto exit;
199 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200200
201 /*
202 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
203 */
204 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
205 {
206 p = buf;
207 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
208 use_len = buf_len;
209
210 while( use_len > 0 )
211 {
212 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
213 chain[i] ^= p[i];
214 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
215 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
216 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
217
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100218 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ) ) != 0 )
219 {
220 goto exit;
221 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200222 }
223
224 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
225
226 /*
227 * Update IV
228 */
229 buf[3]++;
230 }
231
232 /*
233 * Do final encryption with reduced data
234 */
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100235 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
236 {
237 goto exit;
238 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200239 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
240 p = output;
241
242 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
243 {
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100244 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) ) != 0 )
245 {
246 goto exit;
247 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200248 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
249 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
250 }
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100251exit:
Jens Wiklander817466c2018-05-22 13:49:31 +0200252 mbedtls_aes_free( &aes_ctx );
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100253 /*
254 * tidy up the stack
255 */
256 mbedtls_platform_zeroize( buf, sizeof( buf ) );
257 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
258 mbedtls_platform_zeroize( key, sizeof( key ) );
259 mbedtls_platform_zeroize( chain, sizeof( chain ) );
260 if( 0 != ret )
261 {
262 /*
263 * wipe partial seed from memory
264 */
265 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
266 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200267
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100268 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200269}
270
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100271/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
272 * ctr_drbg_update_internal(ctx, provided_data)
273 * implements
274 * CTR_DRBG_Update(provided_data, Key, V)
275 * with inputs and outputs
276 * ctx->aes_ctx = Key
277 * ctx->counter = V
278 */
Jens Wiklander817466c2018-05-22 13:49:31 +0200279static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
280 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
281{
282 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
283 unsigned char *p = tmp;
284 int i, j;
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100285 int ret = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200286
287 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
288
289 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
290 {
291 /*
292 * Increase counter
293 */
294 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
295 if( ++ctx->counter[i - 1] != 0 )
296 break;
297
298 /*
299 * Crypt counter block
300 */
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100301 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 )
302 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200303
304 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
305 }
306
307 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
308 tmp[i] ^= data[i];
309
310 /*
311 * Update key and counter
312 */
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100313 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
314 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200315 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
316
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100317exit:
318 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
319 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200320}
321
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100322/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
323 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
324 * implements
325 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
326 * security_strength) -> initial_working_state
327 * with inputs
328 * ctx->counter = all-bits-0
329 * ctx->aes_ctx = context from all-bits-0 key
330 * additional[:add_len] = entropy_input || nonce || personalization_string
331 * and with outputs
332 * ctx = initial_working_state
333 */
334int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
335 const unsigned char *additional,
336 size_t add_len )
Jens Wiklander817466c2018-05-22 13:49:31 +0200337{
338 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100339 int ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200340
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100341 if( add_len == 0 )
342 return( 0 );
Jens Wiklander817466c2018-05-22 13:49:31 +0200343
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100344 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
345 goto exit;
346 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
347 goto exit;
348
349exit:
350 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
351 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200352}
353
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100354#if !defined(MBEDTLS_DEPRECATED_REMOVED)
355void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
356 const unsigned char *additional,
357 size_t add_len )
358{
359 /* MAX_INPUT would be more logical here, but we have to match
360 * block_cipher_df()'s limits since we can't propagate errors */
361 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
362 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
363 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
364}
365#endif /* MBEDTLS_DEPRECATED_REMOVED */
366
367/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
368 * mbedtls_ctr_drbg_reseed(ctx, additional, len)
369 * implements
370 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
371 * -> new_working_state
372 * with inputs
373 * ctx contains working_state
374 * additional[:len] = additional_input
375 * and entropy_input comes from calling ctx->f_entropy
376 * and with output
377 * ctx contains new_working_state
378 */
Jens Wiklander817466c2018-05-22 13:49:31 +0200379int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
380 const unsigned char *additional, size_t len )
381{
382 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
383 size_t seedlen = 0;
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100384 int ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200385
386 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
387 len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
388 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
389
390 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
391
392 /*
393 * Gather entropy_len bytes of entropy to seed state
394 */
395 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
396 ctx->entropy_len ) )
397 {
398 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
399 }
400
401 seedlen += ctx->entropy_len;
402
403 /*
404 * Add additional data
405 */
406 if( additional && len )
407 {
408 memcpy( seed + seedlen, additional, len );
409 seedlen += len;
410 }
411
412 /*
413 * Reduce to 384 bits
414 */
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100415 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
416 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200417
418 /*
419 * Update state
420 */
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100421 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
422 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200423 ctx->reseed_counter = 1;
424
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100425exit:
426 mbedtls_platform_zeroize( seed, sizeof( seed ) );
427 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200428}
429
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100430/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
431 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
432 * implements
433 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
434 * -> working_state_after_reseed
435 * if required, then
436 * CTR_DRBG_Generate(working_state_after_reseed,
437 * requested_number_of_bits, additional_input)
438 * -> status, returned_bits, new_working_state
439 * with inputs
440 * ctx contains working_state
441 * requested_number_of_bits = 8 * output_len
442 * additional[:add_len] = additional_input
443 * and entropy_input comes from calling ctx->f_entropy
444 * and with outputs
445 * status = SUCCESS (this function does the reseed internally)
446 * returned_bits = output[:output_len]
447 * ctx contains new_working_state
448 */
Jens Wiklander817466c2018-05-22 13:49:31 +0200449int mbedtls_ctr_drbg_random_with_add( void *p_rng,
450 unsigned char *output, size_t output_len,
451 const unsigned char *additional, size_t add_len )
452{
453 int ret = 0;
454 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
455 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
456 unsigned char *p = output;
457 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
458 int i;
459 size_t use_len;
460
461 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
462 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
463
464 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
465 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
466
467 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
468
469 if( ctx->reseed_counter > ctx->reseed_interval ||
470 ctx->prediction_resistance )
471 {
472 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100473 {
Jens Wiklander817466c2018-05-22 13:49:31 +0200474 return( ret );
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100475 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200476 add_len = 0;
477 }
478
479 if( add_len > 0 )
480 {
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100481 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
482 goto exit;
483 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
484 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200485 }
486
487 while( output_len > 0 )
488 {
489 /*
490 * Increase counter
491 */
492 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
493 if( ++ctx->counter[i - 1] != 0 )
494 break;
495
496 /*
497 * Crypt counter block
498 */
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100499 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 )
500 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200501
502 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
503 output_len;
504 /*
505 * Copy random block to destination
506 */
507 memcpy( p, tmp, use_len );
508 p += use_len;
509 output_len -= use_len;
510 }
511
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100512 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
513 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200514
515 ctx->reseed_counter++;
516
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100517exit:
518 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
519 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200520 return( 0 );
521}
522
523int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
524{
525 int ret;
526 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
527
528#if defined(MBEDTLS_THREADING_C)
529 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
530 return( ret );
531#endif
532
533 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
534
535#if defined(MBEDTLS_THREADING_C)
536 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
537 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
538#endif
539
540 return( ret );
541}
542
543#if defined(MBEDTLS_FS_IO)
544int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
545{
546 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
547 FILE *f;
548 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
549
550 if( ( f = fopen( path, "wb" ) ) == NULL )
551 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
552
553 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
554 goto exit;
555
556 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
Jens Wiklander817466c2018-05-22 13:49:31 +0200557 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100558 else
559 ret = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200560
561exit:
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100562 mbedtls_platform_zeroize( buf, sizeof( buf ) );
563
Jens Wiklander817466c2018-05-22 13:49:31 +0200564 fclose( f );
565 return( ret );
566}
567
568int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
569{
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100570 int ret = 0;
571 FILE *f = NULL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200572 size_t n;
573 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100574 unsigned char c;
Jens Wiklander817466c2018-05-22 13:49:31 +0200575
576 if( ( f = fopen( path, "rb" ) ) == NULL )
577 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
578
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100579 n = fread( buf, 1, sizeof( buf ), f );
580 if( fread( &c, 1, 1, f ) != 0 )
Jens Wiklander817466c2018-05-22 13:49:31 +0200581 {
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100582 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
583 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200584 }
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100585 if( n == 0 || ferror( f ) )
Jens Wiklander817466c2018-05-22 13:49:31 +0200586 {
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100587 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
588 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200589 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200590 fclose( f );
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100591 f = NULL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200592
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100593 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
Jens Wiklander817466c2018-05-22 13:49:31 +0200594
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100595exit:
596 mbedtls_platform_zeroize( buf, sizeof( buf ) );
597 if( f != NULL )
598 fclose( f );
599 if( ret != 0 )
600 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200601 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
602}
603#endif /* MBEDTLS_FS_IO */
604
605#if defined(MBEDTLS_SELF_TEST)
606
607static const unsigned char entropy_source_pr[96] =
608 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
609 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
610 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
611 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
612 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
613 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
614 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
615 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
616 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
617 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
618 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
619 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
620
621static const unsigned char entropy_source_nopr[64] =
622 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
623 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
624 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
625 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
626 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
627 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
628 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
629 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
630
631static const unsigned char nonce_pers_pr[16] =
632 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
633 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
634
635static const unsigned char nonce_pers_nopr[16] =
636 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
637 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
638
639static const unsigned char result_pr[16] =
640 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
641 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
642
643static const unsigned char result_nopr[16] =
644 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
645 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
646
647static size_t test_offset;
648static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
649 size_t len )
650{
651 const unsigned char *p = data;
652 memcpy( buf, p + test_offset, len );
653 test_offset += len;
654 return( 0 );
655}
656
657#define CHK( c ) if( (c) != 0 ) \
658 { \
659 if( verbose != 0 ) \
660 mbedtls_printf( "failed\n" ); \
661 return( 1 ); \
662 }
663
664/*
665 * Checkup routine
666 */
667int mbedtls_ctr_drbg_self_test( int verbose )
668{
669 mbedtls_ctr_drbg_context ctx;
670 unsigned char buf[16];
671
672 mbedtls_ctr_drbg_init( &ctx );
673
674 /*
675 * Based on a NIST CTR_DRBG test vector (PR = True)
676 */
677 if( verbose != 0 )
678 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
679
680 test_offset = 0;
681 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
682 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
683 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
684 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
685 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
686 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
687
688 mbedtls_ctr_drbg_free( &ctx );
689
690 if( verbose != 0 )
691 mbedtls_printf( "passed\n" );
692
693 /*
694 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
695 */
696 if( verbose != 0 )
697 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
698
699 mbedtls_ctr_drbg_init( &ctx );
700
701 test_offset = 0;
702 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
703 (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
704 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
705 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
706 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
707 CHK( memcmp( buf, result_nopr, 16 ) );
708
709 mbedtls_ctr_drbg_free( &ctx );
710
711 if( verbose != 0 )
712 mbedtls_printf( "passed\n" );
713
714 if( verbose != 0 )
715 mbedtls_printf( "\n" );
716
717 return( 0 );
718}
719#endif /* MBEDTLS_SELF_TEST */
720
721#endif /* MBEDTLS_CTR_DRBG_C */