blob: ca9617173f7bbfa949d7c21a0e4537ab26f2b642 [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"
Jerome Forissier11fa71b2020-04-20 17:17:56 +020037#include "mbedtls/error.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020038
39#include <string.h>
40
41#if defined(MBEDTLS_FS_IO)
42#include <stdio.h>
43#endif
44
45#if defined(MBEDTLS_SELF_TEST)
46#if defined(MBEDTLS_PLATFORM_C)
47#include "mbedtls/platform.h"
48#else
49#include <stdio.h>
50#define mbedtls_printf printf
51#endif /* MBEDTLS_PLATFORM_C */
52#endif /* MBEDTLS_SELF_TEST */
53
Jens Wiklander817466c2018-05-22 13:49:31 +020054/*
55 * CTR_DRBG context initialization
56 */
57void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
58{
59 memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
Jerome Forissier11fa71b2020-04-20 17:17:56 +020060 /* Indicate that the entropy nonce length is not set explicitly.
61 * See mbedtls_ctr_drbg_set_nonce_len(). */
62 ctx->reseed_counter = -1;
Jens Wiklander817466c2018-05-22 13:49:31 +020063
64#if defined(MBEDTLS_THREADING_C)
65 mbedtls_mutex_init( &ctx->mutex );
66#endif
67}
68
Jens Wiklander817466c2018-05-22 13:49:31 +020069void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
70{
71 if( ctx == NULL )
72 return;
73
74#if defined(MBEDTLS_THREADING_C)
75 mbedtls_mutex_free( &ctx->mutex );
76#endif
77 mbedtls_aes_free( &ctx->aes_ctx );
Jens Wiklander3d3b0592019-03-20 15:30:29 +010078 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Jens Wiklander817466c2018-05-22 13:49:31 +020079}
80
Jerome Forissier11fa71b2020-04-20 17:17:56 +020081void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx,
82 int resistance )
Jens Wiklander817466c2018-05-22 13:49:31 +020083{
84 ctx->prediction_resistance = resistance;
85}
86
Jerome Forissier11fa71b2020-04-20 17:17:56 +020087void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx,
88 size_t len )
Jens Wiklander817466c2018-05-22 13:49:31 +020089{
90 ctx->entropy_len = len;
91}
92
Jerome Forissier11fa71b2020-04-20 17:17:56 +020093int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx,
94 size_t len )
95{
96 /* If mbedtls_ctr_drbg_seed() has already been called, it's
97 * too late. Return the error code that's closest to making sense. */
98 if( ctx->f_entropy != NULL )
99 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
100
101 if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
102 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
103#if SIZE_MAX > INT_MAX
104 /* This shouldn't be an issue because
105 * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible
106 * configuration, but make sure anyway. */
107 if( len > INT_MAX )
108 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
109#endif
110
111 /* For backward compatibility with Mbed TLS <= 2.19, store the
112 * entropy nonce length in a field that already exists, but isn't
113 * used until after the initial seeding. */
114 /* Due to the capping of len above, the value fits in an int. */
115 ctx->reseed_counter = (int) len;
116 return( 0 );
117}
118
119void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx,
120 int interval )
Jens Wiklander817466c2018-05-22 13:49:31 +0200121{
122 ctx->reseed_interval = interval;
123}
124
125static int block_cipher_df( unsigned char *output,
126 const unsigned char *data, size_t data_len )
127{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200128 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
129 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
Jens Wiklander817466c2018-05-22 13:49:31 +0200130 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
131 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
132 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
133 unsigned char *p, *iv;
134 mbedtls_aes_context aes_ctx;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100135 int ret = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200136
137 int i, j;
138 size_t buf_len, use_len;
139
140 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
141 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
142
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200143 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
144 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
Jens Wiklander817466c2018-05-22 13:49:31 +0200145 mbedtls_aes_init( &aes_ctx );
146
147 /*
148 * Construct IV (16 bytes) and S in buffer
149 * IV = Counter (in 32-bits) padded to 16 with zeroes
150 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
151 * data || 0x80
152 * (Total is padded to a multiple of 16-bytes with zeroes)
153 */
154 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
155 *p++ = ( data_len >> 24 ) & 0xff;
156 *p++ = ( data_len >> 16 ) & 0xff;
157 *p++ = ( data_len >> 8 ) & 0xff;
158 *p++ = ( data_len ) & 0xff;
159 p += 3;
160 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
161 memcpy( p, data, data_len );
162 p[data_len] = 0x80;
163
164 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
165
166 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
167 key[i] = i;
168
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200169 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key,
170 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100171 {
172 goto exit;
173 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200174
175 /*
176 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
177 */
178 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
179 {
180 p = buf;
181 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
182 use_len = buf_len;
183
184 while( use_len > 0 )
185 {
186 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
187 chain[i] ^= p[i];
188 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
189 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
190 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
191
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200192 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
193 chain, chain ) ) != 0 )
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100194 {
195 goto exit;
196 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200197 }
198
199 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
200
201 /*
202 * Update IV
203 */
204 buf[3]++;
205 }
206
207 /*
208 * Do final encryption with reduced data
209 */
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200210 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp,
211 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100212 {
213 goto exit;
214 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200215 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
216 p = output;
217
218 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
219 {
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200220 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
221 iv, iv ) ) != 0 )
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100222 {
223 goto exit;
224 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200225 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
226 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
227 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100228exit:
Jens Wiklander817466c2018-05-22 13:49:31 +0200229 mbedtls_aes_free( &aes_ctx );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100230 /*
231 * tidy up the stack
232 */
233 mbedtls_platform_zeroize( buf, sizeof( buf ) );
234 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
235 mbedtls_platform_zeroize( key, sizeof( key ) );
236 mbedtls_platform_zeroize( chain, sizeof( chain ) );
237 if( 0 != ret )
238 {
239 /*
240 * wipe partial seed from memory
241 */
242 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
243 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200244
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100245 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200246}
247
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100248/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
249 * ctr_drbg_update_internal(ctx, provided_data)
250 * implements
251 * CTR_DRBG_Update(provided_data, Key, V)
252 * with inputs and outputs
253 * ctx->aes_ctx = Key
254 * ctx->counter = V
255 */
Jens Wiklander817466c2018-05-22 13:49:31 +0200256static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200257 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Jens Wiklander817466c2018-05-22 13:49:31 +0200258{
259 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
260 unsigned char *p = tmp;
261 int i, j;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100262 int ret = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200263
264 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
265
266 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
267 {
268 /*
269 * Increase counter
270 */
271 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
272 if( ++ctx->counter[i - 1] != 0 )
273 break;
274
275 /*
276 * Crypt counter block
277 */
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200278 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
279 ctx->counter, p ) ) != 0 )
280 {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100281 goto exit;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200282 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200283
284 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
285 }
286
287 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
288 tmp[i] ^= data[i];
289
290 /*
291 * Update key and counter
292 */
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200293 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp,
294 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
295 {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100296 goto exit;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200297 }
298 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
299 MBEDTLS_CTR_DRBG_BLOCKSIZE );
Jens Wiklander817466c2018-05-22 13:49:31 +0200300
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100301exit:
302 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
303 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200304}
305
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100306/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
307 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
308 * implements
309 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
310 * security_strength) -> initial_working_state
311 * with inputs
312 * ctx->counter = all-bits-0
313 * ctx->aes_ctx = context from all-bits-0 key
314 * additional[:add_len] = entropy_input || nonce || personalization_string
315 * and with outputs
316 * ctx = initial_working_state
317 */
318int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
319 const unsigned char *additional,
320 size_t add_len )
Jens Wiklander817466c2018-05-22 13:49:31 +0200321{
322 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200323 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200324
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100325 if( add_len == 0 )
326 return( 0 );
Jens Wiklander817466c2018-05-22 13:49:31 +0200327
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100328 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
329 goto exit;
330 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
331 goto exit;
332
333exit:
334 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
335 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200336}
337
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100338#if !defined(MBEDTLS_DEPRECATED_REMOVED)
339void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
340 const unsigned char *additional,
341 size_t add_len )
342{
343 /* MAX_INPUT would be more logical here, but we have to match
344 * block_cipher_df()'s limits since we can't propagate errors */
345 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
346 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
347 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
348}
349#endif /* MBEDTLS_DEPRECATED_REMOVED */
350
351/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200352 * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100353 * implements
354 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
355 * -> new_working_state
356 * with inputs
357 * ctx contains working_state
358 * additional[:len] = additional_input
359 * and entropy_input comes from calling ctx->f_entropy
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200360 * for (ctx->entropy_len + nonce_len) bytes
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100361 * and with output
362 * ctx contains new_working_state
363 */
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200364static int mbedtls_ctr_drbg_reseed_internal( mbedtls_ctr_drbg_context *ctx,
365 const unsigned char *additional,
366 size_t len,
367 size_t nonce_len )
Jens Wiklander817466c2018-05-22 13:49:31 +0200368{
369 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
370 size_t seedlen = 0;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200371 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200372
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200373 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
374 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
375 if( nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
376 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
377 if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len )
Jens Wiklander817466c2018-05-22 13:49:31 +0200378 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
379
380 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
381
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200382 /* Gather entropy_len bytes of entropy to seed state. */
383 if( 0 != ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) )
Jens Wiklander817466c2018-05-22 13:49:31 +0200384 {
385 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
386 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200387 seedlen += ctx->entropy_len;
388
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200389 /* Gather entropy for a nonce if requested. */
390 if( nonce_len != 0 )
391 {
392 if( 0 != ctx->f_entropy( ctx->p_entropy, seed, nonce_len ) )
393 {
394 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
395 }
396 seedlen += nonce_len;
397 }
398
399 /* Add additional data if provided. */
400 if( additional != NULL && len != 0 )
Jens Wiklander817466c2018-05-22 13:49:31 +0200401 {
402 memcpy( seed + seedlen, additional, len );
403 seedlen += len;
404 }
405
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200406 /* Reduce to 384 bits. */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100407 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
408 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200409
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200410 /* Update state. */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100411 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
412 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200413 ctx->reseed_counter = 1;
414
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100415exit:
416 mbedtls_platform_zeroize( seed, sizeof( seed ) );
417 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200418}
419
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200420int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
421 const unsigned char *additional, size_t len )
422{
423 return( mbedtls_ctr_drbg_reseed_internal( ctx, additional, len, 0 ) );
424}
425
426/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
427 * is sufficient to achieve the maximum security strength given the key
428 * size and entropy length. If there is enough entropy in the initial
429 * call to the entropy function to serve as both the entropy input and
430 * the nonce, don't make a second call to get a nonce. */
431static size_t good_nonce_len( size_t entropy_len )
432{
433 if( entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 )
434 return( 0 );
435 else
436 return( ( entropy_len + 1 ) / 2 );
437}
438
Jerome Forissier5b25c762020-04-07 11:18:49 +0200439/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
440 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
441 * implements
442 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
443 * security_strength) -> initial_working_state
444 * with inputs
445 * custom[:len] = nonce || personalization_string
446 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
447 * and with outputs
448 * ctx = initial_working_state
449 */
450int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
451 int (*f_entropy)(void *, unsigned char *, size_t),
452 void *p_entropy,
453 const unsigned char *custom,
454 size_t len )
455{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200456 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200457 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200458 size_t nonce_len;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200459
460 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
461
462 mbedtls_aes_init( &ctx->aes_ctx );
463
464 ctx->f_entropy = f_entropy;
465 ctx->p_entropy = p_entropy;
466
467 if( ctx->entropy_len == 0 )
468 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200469 /* ctx->reseed_counter contains the desired amount of entropy to
470 * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
471 * If it's -1, indicating that the entropy nonce length was not set
472 * explicitly, use a sufficiently large nonce for security. */
473 nonce_len = ( ctx->reseed_counter >= 0 ?
474 (size_t) ctx->reseed_counter :
475 good_nonce_len( ctx->entropy_len ) );
476
Jerome Forissier5b25c762020-04-07 11:18:49 +0200477 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
478
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200479 /* Initialize with an empty key. */
480 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
481 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Jerome Forissier5b25c762020-04-07 11:18:49 +0200482 {
483 return( ret );
484 }
485
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200486 /* Do the initial seeding. */
487 if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len,
488 nonce_len ) ) != 0 )
Jerome Forissier5b25c762020-04-07 11:18:49 +0200489 {
490 return( ret );
491 }
492 return( 0 );
493}
494
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100495/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
496 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
497 * implements
498 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
499 * -> working_state_after_reseed
500 * if required, then
501 * CTR_DRBG_Generate(working_state_after_reseed,
502 * requested_number_of_bits, additional_input)
503 * -> status, returned_bits, new_working_state
504 * with inputs
505 * ctx contains working_state
506 * requested_number_of_bits = 8 * output_len
507 * additional[:add_len] = additional_input
508 * and entropy_input comes from calling ctx->f_entropy
509 * and with outputs
510 * status = SUCCESS (this function does the reseed internally)
511 * returned_bits = output[:output_len]
512 * ctx contains new_working_state
513 */
Jens Wiklander817466c2018-05-22 13:49:31 +0200514int mbedtls_ctr_drbg_random_with_add( void *p_rng,
515 unsigned char *output, size_t output_len,
516 const unsigned char *additional, size_t add_len )
517{
518 int ret = 0;
519 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
520 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
521 unsigned char *p = output;
522 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
523 int i;
524 size_t use_len;
525
526 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
527 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
528
529 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
530 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
531
532 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
533
534 if( ctx->reseed_counter > ctx->reseed_interval ||
535 ctx->prediction_resistance )
536 {
537 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100538 {
Jens Wiklander817466c2018-05-22 13:49:31 +0200539 return( ret );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100540 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200541 add_len = 0;
542 }
543
544 if( add_len > 0 )
545 {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100546 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
547 goto exit;
548 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
549 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200550 }
551
552 while( output_len > 0 )
553 {
554 /*
555 * Increase counter
556 */
557 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
558 if( ++ctx->counter[i - 1] != 0 )
559 break;
560
561 /*
562 * Crypt counter block
563 */
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200564 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
565 ctx->counter, tmp ) ) != 0 )
566 {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100567 goto exit;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200568 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200569
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200570 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE )
571 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
Jens Wiklander817466c2018-05-22 13:49:31 +0200572 /*
573 * Copy random block to destination
574 */
575 memcpy( p, tmp, use_len );
576 p += use_len;
577 output_len -= use_len;
578 }
579
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100580 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
581 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200582
583 ctx->reseed_counter++;
584
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100585exit:
586 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
587 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
Jerome Forissier5b25c762020-04-07 11:18:49 +0200588 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200589}
590
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200591int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output,
592 size_t output_len )
Jens Wiklander817466c2018-05-22 13:49:31 +0200593{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200594 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200595 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
596
597#if defined(MBEDTLS_THREADING_C)
598 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
599 return( ret );
600#endif
601
602 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
603
604#if defined(MBEDTLS_THREADING_C)
605 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
606 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
607#endif
608
609 return( ret );
610}
611
612#if defined(MBEDTLS_FS_IO)
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200613int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx,
614 const char *path )
Jens Wiklander817466c2018-05-22 13:49:31 +0200615{
616 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
617 FILE *f;
618 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
619
620 if( ( f = fopen( path, "wb" ) ) == NULL )
621 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
622
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200623 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf,
624 MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Jens Wiklander817466c2018-05-22 13:49:31 +0200625 goto exit;
626
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200627 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) !=
628 MBEDTLS_CTR_DRBG_MAX_INPUT )
629 {
Jens Wiklander817466c2018-05-22 13:49:31 +0200630 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200631 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100632 else
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200633 {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100634 ret = 0;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200635 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200636
637exit:
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100638 mbedtls_platform_zeroize( buf, sizeof( buf ) );
639
Jens Wiklander817466c2018-05-22 13:49:31 +0200640 fclose( f );
641 return( ret );
642}
643
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200644int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx,
645 const char *path )
Jens Wiklander817466c2018-05-22 13:49:31 +0200646{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100647 int ret = 0;
648 FILE *f = NULL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200649 size_t n;
650 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100651 unsigned char c;
Jens Wiklander817466c2018-05-22 13:49:31 +0200652
653 if( ( f = fopen( path, "rb" ) ) == NULL )
654 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
655
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100656 n = fread( buf, 1, sizeof( buf ), f );
657 if( fread( &c, 1, 1, f ) != 0 )
Jens Wiklander817466c2018-05-22 13:49:31 +0200658 {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100659 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
660 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200661 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100662 if( n == 0 || ferror( f ) )
Jens Wiklander817466c2018-05-22 13:49:31 +0200663 {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100664 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
665 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200666 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200667 fclose( f );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100668 f = NULL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200669
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100670 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
Jens Wiklander817466c2018-05-22 13:49:31 +0200671
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100672exit:
673 mbedtls_platform_zeroize( buf, sizeof( buf ) );
674 if( f != NULL )
675 fclose( f );
676 if( ret != 0 )
677 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200678 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
679}
680#endif /* MBEDTLS_FS_IO */
681
682#if defined(MBEDTLS_SELF_TEST)
683
684static const unsigned char entropy_source_pr[96] =
685 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
686 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
687 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
688 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
689 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
690 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
691 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
692 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
693 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
694 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
695 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
696 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
697
698static const unsigned char entropy_source_nopr[64] =
699 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
700 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
701 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
702 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
703 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
704 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
705 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
706 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
707
708static const unsigned char nonce_pers_pr[16] =
709 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
710 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
711
712static const unsigned char nonce_pers_nopr[16] =
713 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
714 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
715
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200716#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
717static const unsigned char result_pr[16] =
718 { 0x95, 0x3c, 0xa5, 0xbd, 0x44, 0x1, 0x34, 0xb7,
719 0x13, 0x58, 0x3e, 0x6a, 0x6c, 0x7e, 0x88, 0x8a };
720
721static const unsigned char result_nopr[16] =
722 { 0x6c, 0x25, 0x27, 0x95, 0xa3, 0x62, 0xd6, 0xdb,
723 0x90, 0xfd, 0x69, 0xb5, 0x42, 0x9, 0x4b, 0x84 };
724#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Jens Wiklander817466c2018-05-22 13:49:31 +0200725static const unsigned char result_pr[16] =
726 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
727 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
728
729static const unsigned char result_nopr[16] =
730 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
731 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200732#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Jens Wiklander817466c2018-05-22 13:49:31 +0200733
734static size_t test_offset;
735static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
736 size_t len )
737{
738 const unsigned char *p = data;
739 memcpy( buf, p + test_offset, len );
740 test_offset += len;
741 return( 0 );
742}
743
744#define CHK( c ) if( (c) != 0 ) \
745 { \
746 if( verbose != 0 ) \
747 mbedtls_printf( "failed\n" ); \
748 return( 1 ); \
749 }
750
751/*
752 * Checkup routine
753 */
754int mbedtls_ctr_drbg_self_test( int verbose )
755{
756 mbedtls_ctr_drbg_context ctx;
757 unsigned char buf[16];
758
759 mbedtls_ctr_drbg_init( &ctx );
760
761 /*
762 * Based on a NIST CTR_DRBG test vector (PR = True)
763 */
764 if( verbose != 0 )
765 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
766
767 test_offset = 0;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200768 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200769 mbedtls_ctr_drbg_set_nonce_len( &ctx, 0 );
Jerome Forissier5b25c762020-04-07 11:18:49 +0200770 CHK( mbedtls_ctr_drbg_seed( &ctx,
771 ctr_drbg_self_test_entropy,
772 (void *) entropy_source_pr,
773 nonce_pers_pr, 16 ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200774 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
775 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
776 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
777 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
778
779 mbedtls_ctr_drbg_free( &ctx );
780
781 if( verbose != 0 )
782 mbedtls_printf( "passed\n" );
783
784 /*
785 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
786 */
787 if( verbose != 0 )
788 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
789
790 mbedtls_ctr_drbg_init( &ctx );
791
792 test_offset = 0;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200793 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200794 mbedtls_ctr_drbg_set_nonce_len( &ctx, 0 );
Jerome Forissier5b25c762020-04-07 11:18:49 +0200795 CHK( mbedtls_ctr_drbg_seed( &ctx,
796 ctr_drbg_self_test_entropy,
797 (void *) entropy_source_nopr,
798 nonce_pers_nopr, 16 ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200799 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
800 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
801 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
802 CHK( memcmp( buf, result_nopr, 16 ) );
803
804 mbedtls_ctr_drbg_free( &ctx );
805
806 if( verbose != 0 )
807 mbedtls_printf( "passed\n" );
808
809 if( verbose != 0 )
810 mbedtls_printf( "\n" );
811
812 return( 0 );
813}
814#endif /* MBEDTLS_SELF_TEST */
815
816#endif /* MBEDTLS_CTR_DRBG_C */