blob: a00d66ce872d12b9bb7d99a6022ea12a5a75028a [file] [log] [blame]
Jens Wiklander817466c2018-05-22 13:49:31 +02001/*
2 * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
3 *
Jerome Forissier79013242021-07-28 10:24:04 +02004 * Copyright The Mbed TLS Contributors
5 * 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.
Jens Wiklander817466c2018-05-22 13:49:31 +020018 */
19/*
Jens Wiklander3d3b0592019-03-20 15:30:29 +010020 * The NIST SP 800-90 DRBGs are described in the following publication.
Jens Wiklander817466c2018-05-22 13:49:31 +020021 *
22 * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
23 */
24
Jerome Forissier79013242021-07-28 10:24:04 +020025#include "common.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020026
27#if defined(MBEDTLS_CTR_DRBG_C)
28
29#include "mbedtls/ctr_drbg.h"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010030#include "mbedtls/platform_util.h"
Jerome Forissier11fa71b2020-04-20 17:17:56 +020031#include "mbedtls/error.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020032
33#include <string.h>
34
35#if defined(MBEDTLS_FS_IO)
36#include <stdio.h>
37#endif
38
39#if defined(MBEDTLS_SELF_TEST)
40#if defined(MBEDTLS_PLATFORM_C)
41#include "mbedtls/platform.h"
42#else
43#include <stdio.h>
44#define mbedtls_printf printf
45#endif /* MBEDTLS_PLATFORM_C */
46#endif /* MBEDTLS_SELF_TEST */
47
Jens Wiklander817466c2018-05-22 13:49:31 +020048/*
49 * CTR_DRBG context initialization
50 */
51void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
52{
53 memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
Jerome Forissier11fa71b2020-04-20 17:17:56 +020054 /* Indicate that the entropy nonce length is not set explicitly.
55 * See mbedtls_ctr_drbg_set_nonce_len(). */
56 ctx->reseed_counter = -1;
Jens Wiklander817466c2018-05-22 13:49:31 +020057
Jerome Forissier79013242021-07-28 10:24:04 +020058 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
Jens Wiklander817466c2018-05-22 13:49:31 +020059}
60
Jerome Forissier79013242021-07-28 10:24:04 +020061/*
62 * This function resets CTR_DRBG context to the state immediately
63 * after initial call of mbedtls_ctr_drbg_init().
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)
Jerome Forissier79013242021-07-28 10:24:04 +020071 /* The mutex is initialized iff f_entropy is set. */
72 if( ctx->f_entropy != NULL )
73 mbedtls_mutex_free( &ctx->mutex );
Jens Wiklander817466c2018-05-22 13:49:31 +020074#endif
75 mbedtls_aes_free( &ctx->aes_ctx );
Jens Wiklander3d3b0592019-03-20 15:30:29 +010076 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Jerome Forissier79013242021-07-28 10:24:04 +020077 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
78 ctx->reseed_counter = -1;
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;
Jerome Forissier039e02d2022-08-09 17:10:15 +0200155 MBEDTLS_PUT_UINT32_BE( data_len, p, 0);
156 p += 4 + 3;
Jens Wiklander817466c2018-05-22 13:49:31 +0200157 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
158 memcpy( p, data, data_len );
159 p[data_len] = 0x80;
160
161 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
162
163 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
164 key[i] = i;
165
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200166 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key,
167 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100168 {
169 goto exit;
170 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200171
172 /*
173 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
174 */
175 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
176 {
177 p = buf;
178 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
179 use_len = buf_len;
180
181 while( use_len > 0 )
182 {
183 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
184 chain[i] ^= p[i];
185 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
186 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
187 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
188
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200189 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
190 chain, chain ) ) != 0 )
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100191 {
192 goto exit;
193 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200194 }
195
196 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
197
198 /*
199 * Update IV
200 */
201 buf[3]++;
202 }
203
204 /*
205 * Do final encryption with reduced data
206 */
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200207 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp,
208 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100209 {
210 goto exit;
211 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200212 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
213 p = output;
214
215 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
216 {
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200217 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
218 iv, iv ) ) != 0 )
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100219 {
220 goto exit;
221 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200222 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
223 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
224 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100225exit:
Jens Wiklander817466c2018-05-22 13:49:31 +0200226 mbedtls_aes_free( &aes_ctx );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100227 /*
228 * tidy up the stack
229 */
230 mbedtls_platform_zeroize( buf, sizeof( buf ) );
231 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
232 mbedtls_platform_zeroize( key, sizeof( key ) );
233 mbedtls_platform_zeroize( chain, sizeof( chain ) );
234 if( 0 != ret )
235 {
236 /*
237 * wipe partial seed from memory
238 */
239 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
240 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200241
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100242 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200243}
244
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100245/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
246 * ctr_drbg_update_internal(ctx, provided_data)
247 * implements
248 * CTR_DRBG_Update(provided_data, Key, V)
249 * with inputs and outputs
250 * ctx->aes_ctx = Key
251 * ctx->counter = V
252 */
Jens Wiklander817466c2018-05-22 13:49:31 +0200253static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200254 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Jens Wiklander817466c2018-05-22 13:49:31 +0200255{
256 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
257 unsigned char *p = tmp;
258 int i, j;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100259 int ret = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200260
261 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
262
263 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
264 {
265 /*
266 * Increase counter
267 */
268 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
269 if( ++ctx->counter[i - 1] != 0 )
270 break;
271
272 /*
273 * Crypt counter block
274 */
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200275 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
276 ctx->counter, p ) ) != 0 )
277 {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100278 goto exit;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200279 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200280
281 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
282 }
283
284 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
285 tmp[i] ^= data[i];
286
287 /*
288 * Update key and counter
289 */
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200290 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp,
291 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
292 {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100293 goto exit;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200294 }
295 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
296 MBEDTLS_CTR_DRBG_BLOCKSIZE );
Jens Wiklander817466c2018-05-22 13:49:31 +0200297
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100298exit:
299 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
300 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200301}
302
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100303/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
304 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
305 * implements
306 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
307 * security_strength) -> initial_working_state
308 * with inputs
309 * ctx->counter = all-bits-0
310 * ctx->aes_ctx = context from all-bits-0 key
311 * additional[:add_len] = entropy_input || nonce || personalization_string
312 * and with outputs
313 * ctx = initial_working_state
314 */
315int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
316 const unsigned char *additional,
317 size_t add_len )
Jens Wiklander817466c2018-05-22 13:49:31 +0200318{
319 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200320 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200321
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100322 if( add_len == 0 )
323 return( 0 );
Jens Wiklander817466c2018-05-22 13:49:31 +0200324
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100325 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
326 goto exit;
327 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
328 goto exit;
329
330exit:
331 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
332 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200333}
334
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100335#if !defined(MBEDTLS_DEPRECATED_REMOVED)
336void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
337 const unsigned char *additional,
338 size_t add_len )
339{
340 /* MAX_INPUT would be more logical here, but we have to match
341 * block_cipher_df()'s limits since we can't propagate errors */
342 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
343 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
344 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
345}
346#endif /* MBEDTLS_DEPRECATED_REMOVED */
347
348/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200349 * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100350 * implements
351 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
352 * -> new_working_state
353 * with inputs
354 * ctx contains working_state
355 * additional[:len] = additional_input
356 * and entropy_input comes from calling ctx->f_entropy
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200357 * for (ctx->entropy_len + nonce_len) bytes
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100358 * and with output
359 * ctx contains new_working_state
360 */
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200361static int mbedtls_ctr_drbg_reseed_internal( mbedtls_ctr_drbg_context *ctx,
362 const unsigned char *additional,
363 size_t len,
364 size_t nonce_len )
Jens Wiklander817466c2018-05-22 13:49:31 +0200365{
366 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
367 size_t seedlen = 0;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200368 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200369
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200370 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
371 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
372 if( nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
373 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
374 if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len )
Jens Wiklander817466c2018-05-22 13:49:31 +0200375 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
376
377 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
378
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200379 /* Gather entropy_len bytes of entropy to seed state. */
380 if( 0 != ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) )
Jens Wiklander817466c2018-05-22 13:49:31 +0200381 {
382 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
383 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200384 seedlen += ctx->entropy_len;
385
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200386 /* Gather entropy for a nonce if requested. */
387 if( nonce_len != 0 )
388 {
Jerome Forissier79013242021-07-28 10:24:04 +0200389 if( 0 != ctx->f_entropy( ctx->p_entropy, seed + seedlen, nonce_len ) )
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200390 {
391 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
392 }
393 seedlen += nonce_len;
394 }
395
396 /* Add additional data if provided. */
397 if( additional != NULL && len != 0 )
Jens Wiklander817466c2018-05-22 13:49:31 +0200398 {
399 memcpy( seed + seedlen, additional, len );
400 seedlen += len;
401 }
402
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200403 /* Reduce to 384 bits. */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100404 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
405 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200406
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200407 /* Update state. */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100408 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
409 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200410 ctx->reseed_counter = 1;
411
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100412exit:
413 mbedtls_platform_zeroize( seed, sizeof( seed ) );
414 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200415}
416
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200417int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
418 const unsigned char *additional, size_t len )
419{
420 return( mbedtls_ctr_drbg_reseed_internal( ctx, additional, len, 0 ) );
421}
422
423/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
424 * is sufficient to achieve the maximum security strength given the key
425 * size and entropy length. If there is enough entropy in the initial
426 * call to the entropy function to serve as both the entropy input and
427 * the nonce, don't make a second call to get a nonce. */
428static size_t good_nonce_len( size_t entropy_len )
429{
430 if( entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 )
431 return( 0 );
432 else
433 return( ( entropy_len + 1 ) / 2 );
434}
435
Jerome Forissier5b25c762020-04-07 11:18:49 +0200436/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
437 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
438 * implements
439 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
440 * security_strength) -> initial_working_state
441 * with inputs
442 * custom[:len] = nonce || personalization_string
443 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
444 * and with outputs
445 * ctx = initial_working_state
446 */
447int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
448 int (*f_entropy)(void *, unsigned char *, size_t),
449 void *p_entropy,
450 const unsigned char *custom,
451 size_t len )
452{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200453 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200454 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200455 size_t nonce_len;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200456
457 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
458
Jerome Forissier79013242021-07-28 10:24:04 +0200459 /* The mutex is initialized iff f_entropy is set. */
460#if defined(MBEDTLS_THREADING_C)
461 mbedtls_mutex_init( &ctx->mutex );
462#endif
463
Jerome Forissier5b25c762020-04-07 11:18:49 +0200464 mbedtls_aes_init( &ctx->aes_ctx );
465
466 ctx->f_entropy = f_entropy;
467 ctx->p_entropy = p_entropy;
468
469 if( ctx->entropy_len == 0 )
470 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200471 /* ctx->reseed_counter contains the desired amount of entropy to
472 * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
473 * If it's -1, indicating that the entropy nonce length was not set
474 * explicitly, use a sufficiently large nonce for security. */
475 nonce_len = ( ctx->reseed_counter >= 0 ?
476 (size_t) ctx->reseed_counter :
477 good_nonce_len( ctx->entropy_len ) );
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
Jerome Forissier79013242021-07-28 10:24:04 +0200684/* The CTR_DRBG NIST test vectors used here are available at
685 * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip
686 *
687 * The parameters used to derive the test data are:
688 *
689 * [AES-128 use df]
690 * [PredictionResistance = True/False]
691 * [EntropyInputLen = 128]
692 * [NonceLen = 64]
693 * [PersonalizationStringLen = 128]
694 * [AdditionalInputLen = 0]
695 * [ReturnedBitsLen = 512]
696 *
697 * [AES-256 use df]
698 * [PredictionResistance = True/False]
699 * [EntropyInputLen = 256]
700 * [NonceLen = 128]
701 * [PersonalizationStringLen = 256]
702 * [AdditionalInputLen = 0]
703 * [ReturnedBitsLen = 512]
704 *
705 */
Jens Wiklander817466c2018-05-22 13:49:31 +0200706
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200707#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
Jerome Forissier79013242021-07-28 10:24:04 +0200708static const unsigned char entropy_source_pr[] =
709 { 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb,
710 0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92,
711 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8,
712 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20,
713 0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0,
714 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad,
715 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 };
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200716
Jerome Forissier79013242021-07-28 10:24:04 +0200717static const unsigned char entropy_source_nopr[] =
718 { 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45,
719 0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9,
720 0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20,
721 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f,
722 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c };
723
724static const unsigned char pers_pr[] =
725 { 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a,
726 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad };
727
728static const unsigned char pers_nopr[] =
729 { 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c,
730 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f };
731
732static const unsigned char result_pr[] =
733 { 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66,
734 0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff,
735 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10,
736 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30,
737 0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4,
738 0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc,
739 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06,
740 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf };
741
742static const unsigned char result_nopr[] =
743 { 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13,
744 0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0,
745 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf,
746 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2,
747 0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7,
748 0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2,
749 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02,
750 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 };
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200751#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Jens Wiklander817466c2018-05-22 13:49:31 +0200752
Jerome Forissier79013242021-07-28 10:24:04 +0200753static const unsigned char entropy_source_pr[] =
754 { 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49,
755 0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a,
756 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85,
757 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e,
758 0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15,
759 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45,
760 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8,
761 0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c,
762 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3,
763 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce,
764 0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e,
765 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76,
766 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77,
767 0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe };
768
769static const unsigned char entropy_source_nopr[] =
770 { 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d,
771 0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0,
772 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73,
773 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c,
774 0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2,
775 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1,
776 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a,
777 0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb,
778 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a,
779 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 };
780
781static const unsigned char pers_pr[] =
782 { 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33,
783 0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e,
784 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0,
785 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 };
786
787static const unsigned char pers_nopr[] =
788 { 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29,
789 0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf,
790 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb,
791 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b };
792
793static const unsigned char result_pr[] =
794 { 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85,
795 0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d,
796 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62,
797 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d,
798 0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb,
799 0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39,
800 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40,
801 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 };
802
803static const unsigned char result_nopr[] =
804 { 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad,
805 0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3,
806 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b,
807 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14,
808 0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54,
809 0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30,
810 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a,
811 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 };
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200812#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Jens Wiklander817466c2018-05-22 13:49:31 +0200813
814static size_t test_offset;
815static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
816 size_t len )
817{
818 const unsigned char *p = data;
819 memcpy( buf, p + test_offset, len );
820 test_offset += len;
821 return( 0 );
822}
823
824#define CHK( c ) if( (c) != 0 ) \
825 { \
826 if( verbose != 0 ) \
827 mbedtls_printf( "failed\n" ); \
828 return( 1 ); \
829 }
830
Jerome Forissier039e02d2022-08-09 17:10:15 +0200831#define SELF_TEST_OUTPUT_DISCARD_LENGTH 64
Jerome Forissier79013242021-07-28 10:24:04 +0200832
Jens Wiklander817466c2018-05-22 13:49:31 +0200833/*
834 * Checkup routine
835 */
836int mbedtls_ctr_drbg_self_test( int verbose )
837{
838 mbedtls_ctr_drbg_context ctx;
Jerome Forissier79013242021-07-28 10:24:04 +0200839 unsigned char buf[ sizeof( result_pr ) ];
Jens Wiklander817466c2018-05-22 13:49:31 +0200840
841 mbedtls_ctr_drbg_init( &ctx );
842
843 /*
844 * Based on a NIST CTR_DRBG test vector (PR = True)
845 */
846 if( verbose != 0 )
847 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
848
849 test_offset = 0;
Jerome Forissier79013242021-07-28 10:24:04 +0200850 mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE );
851 mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
Jerome Forissier5b25c762020-04-07 11:18:49 +0200852 CHK( mbedtls_ctr_drbg_seed( &ctx,
853 ctr_drbg_self_test_entropy,
854 (void *) entropy_source_pr,
Jerome Forissier79013242021-07-28 10:24:04 +0200855 pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200856 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
Jerome Forissier039e02d2022-08-09 17:10:15 +0200857 CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH ) );
Jerome Forissier79013242021-07-28 10:24:04 +0200858 CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_pr ) ) );
859 CHK( memcmp( buf, result_pr, sizeof( result_pr ) ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200860
861 mbedtls_ctr_drbg_free( &ctx );
862
863 if( verbose != 0 )
864 mbedtls_printf( "passed\n" );
865
866 /*
867 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
868 */
869 if( verbose != 0 )
870 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
871
872 mbedtls_ctr_drbg_init( &ctx );
873
874 test_offset = 0;
Jerome Forissier79013242021-07-28 10:24:04 +0200875 mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
876 mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
Jerome Forissier5b25c762020-04-07 11:18:49 +0200877 CHK( mbedtls_ctr_drbg_seed( &ctx,
878 ctr_drbg_self_test_entropy,
879 (void *) entropy_source_nopr,
Jerome Forissier79013242021-07-28 10:24:04 +0200880 pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200881 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
Jerome Forissier039e02d2022-08-09 17:10:15 +0200882 CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH ) );
Jerome Forissier79013242021-07-28 10:24:04 +0200883 CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_nopr ) ) );
884 CHK( memcmp( buf, result_nopr, sizeof( result_nopr ) ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200885
886 mbedtls_ctr_drbg_free( &ctx );
887
888 if( verbose != 0 )
889 mbedtls_printf( "passed\n" );
890
891 if( verbose != 0 )
892 mbedtls_printf( "\n" );
893
894 return( 0 );
895}
896#endif /* MBEDTLS_SELF_TEST */
897
898#endif /* MBEDTLS_CTR_DRBG_C */