blob: ab52861d578eff65a8d68c156a6876f0e3f0c10f [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;
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 {
Jerome Forissier79013242021-07-28 10:24:04 +0200392 if( 0 != ctx->f_entropy( ctx->p_entropy, seed + seedlen, nonce_len ) )
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200393 {
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
Jerome Forissier79013242021-07-28 10:24:04 +0200462 /* The mutex is initialized iff f_entropy is set. */
463#if defined(MBEDTLS_THREADING_C)
464 mbedtls_mutex_init( &ctx->mutex );
465#endif
466
Jerome Forissier5b25c762020-04-07 11:18:49 +0200467 mbedtls_aes_init( &ctx->aes_ctx );
468
469 ctx->f_entropy = f_entropy;
470 ctx->p_entropy = p_entropy;
471
472 if( ctx->entropy_len == 0 )
473 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200474 /* ctx->reseed_counter contains the desired amount of entropy to
475 * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
476 * If it's -1, indicating that the entropy nonce length was not set
477 * explicitly, use a sufficiently large nonce for security. */
478 nonce_len = ( ctx->reseed_counter >= 0 ?
479 (size_t) ctx->reseed_counter :
480 good_nonce_len( ctx->entropy_len ) );
481
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200482 /* Initialize with an empty key. */
483 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
484 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Jerome Forissier5b25c762020-04-07 11:18:49 +0200485 {
486 return( ret );
487 }
488
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200489 /* Do the initial seeding. */
490 if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len,
491 nonce_len ) ) != 0 )
Jerome Forissier5b25c762020-04-07 11:18:49 +0200492 {
493 return( ret );
494 }
495 return( 0 );
496}
497
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100498/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
499 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
500 * implements
501 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
502 * -> working_state_after_reseed
503 * if required, then
504 * CTR_DRBG_Generate(working_state_after_reseed,
505 * requested_number_of_bits, additional_input)
506 * -> status, returned_bits, new_working_state
507 * with inputs
508 * ctx contains working_state
509 * requested_number_of_bits = 8 * output_len
510 * additional[:add_len] = additional_input
511 * and entropy_input comes from calling ctx->f_entropy
512 * and with outputs
513 * status = SUCCESS (this function does the reseed internally)
514 * returned_bits = output[:output_len]
515 * ctx contains new_working_state
516 */
Jens Wiklander817466c2018-05-22 13:49:31 +0200517int mbedtls_ctr_drbg_random_with_add( void *p_rng,
518 unsigned char *output, size_t output_len,
519 const unsigned char *additional, size_t add_len )
520{
521 int ret = 0;
522 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
523 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
524 unsigned char *p = output;
525 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
526 int i;
527 size_t use_len;
528
529 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
530 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
531
532 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
533 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
534
535 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
536
537 if( ctx->reseed_counter > ctx->reseed_interval ||
538 ctx->prediction_resistance )
539 {
540 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100541 {
Jens Wiklander817466c2018-05-22 13:49:31 +0200542 return( ret );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100543 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200544 add_len = 0;
545 }
546
547 if( add_len > 0 )
548 {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100549 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
550 goto exit;
551 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
552 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200553 }
554
555 while( output_len > 0 )
556 {
557 /*
558 * Increase counter
559 */
560 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
561 if( ++ctx->counter[i - 1] != 0 )
562 break;
563
564 /*
565 * Crypt counter block
566 */
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200567 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
568 ctx->counter, tmp ) ) != 0 )
569 {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100570 goto exit;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200571 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200572
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200573 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE )
574 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
Jens Wiklander817466c2018-05-22 13:49:31 +0200575 /*
576 * Copy random block to destination
577 */
578 memcpy( p, tmp, use_len );
579 p += use_len;
580 output_len -= use_len;
581 }
582
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100583 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
584 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200585
586 ctx->reseed_counter++;
587
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100588exit:
589 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
590 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
Jerome Forissier5b25c762020-04-07 11:18:49 +0200591 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200592}
593
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200594int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output,
595 size_t output_len )
Jens Wiklander817466c2018-05-22 13:49:31 +0200596{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200597 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200598 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
599
600#if defined(MBEDTLS_THREADING_C)
601 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
602 return( ret );
603#endif
604
605 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
606
607#if defined(MBEDTLS_THREADING_C)
608 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
609 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
610#endif
611
612 return( ret );
613}
614
615#if defined(MBEDTLS_FS_IO)
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200616int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx,
617 const char *path )
Jens Wiklander817466c2018-05-22 13:49:31 +0200618{
619 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
620 FILE *f;
621 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
622
623 if( ( f = fopen( path, "wb" ) ) == NULL )
624 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
625
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200626 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf,
627 MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Jens Wiklander817466c2018-05-22 13:49:31 +0200628 goto exit;
629
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200630 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) !=
631 MBEDTLS_CTR_DRBG_MAX_INPUT )
632 {
Jens Wiklander817466c2018-05-22 13:49:31 +0200633 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200634 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100635 else
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200636 {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100637 ret = 0;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200638 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200639
640exit:
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100641 mbedtls_platform_zeroize( buf, sizeof( buf ) );
642
Jens Wiklander817466c2018-05-22 13:49:31 +0200643 fclose( f );
644 return( ret );
645}
646
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200647int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx,
648 const char *path )
Jens Wiklander817466c2018-05-22 13:49:31 +0200649{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100650 int ret = 0;
651 FILE *f = NULL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200652 size_t n;
653 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100654 unsigned char c;
Jens Wiklander817466c2018-05-22 13:49:31 +0200655
656 if( ( f = fopen( path, "rb" ) ) == NULL )
657 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
658
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100659 n = fread( buf, 1, sizeof( buf ), f );
660 if( fread( &c, 1, 1, f ) != 0 )
Jens Wiklander817466c2018-05-22 13:49:31 +0200661 {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100662 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
663 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200664 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100665 if( n == 0 || ferror( f ) )
Jens Wiklander817466c2018-05-22 13:49:31 +0200666 {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100667 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
668 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200669 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200670 fclose( f );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100671 f = NULL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200672
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100673 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
Jens Wiklander817466c2018-05-22 13:49:31 +0200674
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100675exit:
676 mbedtls_platform_zeroize( buf, sizeof( buf ) );
677 if( f != NULL )
678 fclose( f );
679 if( ret != 0 )
680 return( ret );
Jens Wiklander817466c2018-05-22 13:49:31 +0200681 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
682}
683#endif /* MBEDTLS_FS_IO */
684
685#if defined(MBEDTLS_SELF_TEST)
686
Jerome Forissier79013242021-07-28 10:24:04 +0200687/* The CTR_DRBG NIST test vectors used here are available at
688 * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip
689 *
690 * The parameters used to derive the test data are:
691 *
692 * [AES-128 use df]
693 * [PredictionResistance = True/False]
694 * [EntropyInputLen = 128]
695 * [NonceLen = 64]
696 * [PersonalizationStringLen = 128]
697 * [AdditionalInputLen = 0]
698 * [ReturnedBitsLen = 512]
699 *
700 * [AES-256 use df]
701 * [PredictionResistance = True/False]
702 * [EntropyInputLen = 256]
703 * [NonceLen = 128]
704 * [PersonalizationStringLen = 256]
705 * [AdditionalInputLen = 0]
706 * [ReturnedBitsLen = 512]
707 *
708 */
Jens Wiklander817466c2018-05-22 13:49:31 +0200709
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200710#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
Jerome Forissier79013242021-07-28 10:24:04 +0200711static const unsigned char entropy_source_pr[] =
712 { 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb,
713 0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92,
714 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8,
715 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20,
716 0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0,
717 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad,
718 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 };
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200719
Jerome Forissier79013242021-07-28 10:24:04 +0200720static const unsigned char entropy_source_nopr[] =
721 { 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45,
722 0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9,
723 0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20,
724 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f,
725 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c };
726
727static const unsigned char pers_pr[] =
728 { 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a,
729 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad };
730
731static const unsigned char pers_nopr[] =
732 { 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c,
733 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f };
734
735static const unsigned char result_pr[] =
736 { 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66,
737 0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff,
738 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10,
739 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30,
740 0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4,
741 0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc,
742 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06,
743 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf };
744
745static const unsigned char result_nopr[] =
746 { 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13,
747 0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0,
748 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf,
749 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2,
750 0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7,
751 0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2,
752 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02,
753 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 };
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200754#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Jens Wiklander817466c2018-05-22 13:49:31 +0200755
Jerome Forissier79013242021-07-28 10:24:04 +0200756static const unsigned char entropy_source_pr[] =
757 { 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49,
758 0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a,
759 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85,
760 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e,
761 0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15,
762 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45,
763 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8,
764 0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c,
765 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3,
766 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce,
767 0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e,
768 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76,
769 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77,
770 0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe };
771
772static const unsigned char entropy_source_nopr[] =
773 { 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d,
774 0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0,
775 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73,
776 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c,
777 0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2,
778 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1,
779 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a,
780 0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb,
781 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a,
782 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 };
783
784static const unsigned char pers_pr[] =
785 { 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33,
786 0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e,
787 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0,
788 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 };
789
790static const unsigned char pers_nopr[] =
791 { 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29,
792 0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf,
793 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb,
794 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b };
795
796static const unsigned char result_pr[] =
797 { 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85,
798 0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d,
799 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62,
800 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d,
801 0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb,
802 0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39,
803 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40,
804 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 };
805
806static const unsigned char result_nopr[] =
807 { 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad,
808 0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3,
809 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b,
810 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14,
811 0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54,
812 0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30,
813 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a,
814 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 };
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200815#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
Jens Wiklander817466c2018-05-22 13:49:31 +0200816
817static size_t test_offset;
818static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
819 size_t len )
820{
821 const unsigned char *p = data;
822 memcpy( buf, p + test_offset, len );
823 test_offset += len;
824 return( 0 );
825}
826
827#define CHK( c ) if( (c) != 0 ) \
828 { \
829 if( verbose != 0 ) \
830 mbedtls_printf( "failed\n" ); \
831 return( 1 ); \
832 }
833
Jerome Forissier79013242021-07-28 10:24:04 +0200834#define SELF_TEST_OUPUT_DISCARD_LENGTH 64
835
Jens Wiklander817466c2018-05-22 13:49:31 +0200836/*
837 * Checkup routine
838 */
839int mbedtls_ctr_drbg_self_test( int verbose )
840{
841 mbedtls_ctr_drbg_context ctx;
Jerome Forissier79013242021-07-28 10:24:04 +0200842 unsigned char buf[ sizeof( result_pr ) ];
Jens Wiklander817466c2018-05-22 13:49:31 +0200843
844 mbedtls_ctr_drbg_init( &ctx );
845
846 /*
847 * Based on a NIST CTR_DRBG test vector (PR = True)
848 */
849 if( verbose != 0 )
850 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
851
852 test_offset = 0;
Jerome Forissier79013242021-07-28 10:24:04 +0200853 mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE );
854 mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
Jerome Forissier5b25c762020-04-07 11:18:49 +0200855 CHK( mbedtls_ctr_drbg_seed( &ctx,
856 ctr_drbg_self_test_entropy,
857 (void *) entropy_source_pr,
Jerome Forissier79013242021-07-28 10:24:04 +0200858 pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200859 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
Jerome Forissier79013242021-07-28 10:24:04 +0200860 CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUPUT_DISCARD_LENGTH ) );
861 CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_pr ) ) );
862 CHK( memcmp( buf, result_pr, sizeof( result_pr ) ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200863
864 mbedtls_ctr_drbg_free( &ctx );
865
866 if( verbose != 0 )
867 mbedtls_printf( "passed\n" );
868
869 /*
870 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
871 */
872 if( verbose != 0 )
873 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
874
875 mbedtls_ctr_drbg_init( &ctx );
876
877 test_offset = 0;
Jerome Forissier79013242021-07-28 10:24:04 +0200878 mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
879 mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
Jerome Forissier5b25c762020-04-07 11:18:49 +0200880 CHK( mbedtls_ctr_drbg_seed( &ctx,
881 ctr_drbg_self_test_entropy,
882 (void *) entropy_source_nopr,
Jerome Forissier79013242021-07-28 10:24:04 +0200883 pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200884 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
Jerome Forissier79013242021-07-28 10:24:04 +0200885 CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUPUT_DISCARD_LENGTH ) );
886 CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_nopr ) ) );
887 CHK( memcmp( buf, result_nopr, sizeof( result_nopr ) ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200888
889 mbedtls_ctr_drbg_free( &ctx );
890
891 if( verbose != 0 )
892 mbedtls_printf( "passed\n" );
893
894 if( verbose != 0 )
895 mbedtls_printf( "\n" );
896
897 return( 0 );
898}
899#endif /* MBEDTLS_SELF_TEST */
900
901#endif /* MBEDTLS_CTR_DRBG_C */