blob: 85bd04f2bcee4c045f1a1ff386da584f8ddbc927 [file] [log] [blame]
Paul Bakker0e04d0e2011-11-27 14:46:59 +00001/*
2 * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
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.
Paul Bakker0e04d0e2011-11-27 14:46:59 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000020 */
21/*
Paul Sokolovsky8d6d8c82018-02-10 11:11:41 +020022 * The NIST SP 800-90 DRBGs are described in the following publication.
Paul Bakker0e04d0e2011-11-27 14:46:59 +000023 *
24 * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
25 */
26
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020027#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000028#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020029#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020030#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020031#endif
Paul Bakker0e04d0e2011-11-27 14:46:59 +000032
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020033#if defined(MBEDTLS_CTR_DRBG_C)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000034
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000035#include "mbedtls/ctr_drbg.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050036#include "mbedtls/platform_util.h"
Paul Bakker0e04d0e2011-11-27 14:46:59 +000037
Rich Evans00ab4702015-02-06 13:43:58 +000038#include <string.h>
39
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020040#if defined(MBEDTLS_FS_IO)
Paul Bakkerfc754a92011-12-05 13:23:51 +000041#include <stdio.h>
42#endif
43
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if defined(MBEDTLS_SELF_TEST)
45#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010047#else
Rich Evans00ab4702015-02-06 13:43:58 +000048#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020049#define mbedtls_printf printf
50#endif /* MBEDTLS_PLATFORM_C */
51#endif /* MBEDTLS_SELF_TEST */
Paul Bakker7dc4c442014-02-01 22:50:26 +010052
Paul Bakker18d32912011-12-10 21:42:49 +000053/*
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020054 * CTR_DRBG context initialization
55 */
56void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
57{
58 memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010059
60#if defined(MBEDTLS_THREADING_C)
61 mbedtls_mutex_init( &ctx->mutex );
62#endif
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020063}
64
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020065void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
Paul Bakkerfff03662014-06-18 16:21:25 +020066{
67 if( ctx == NULL )
68 return;
69
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010070#if defined(MBEDTLS_THREADING_C)
71 mbedtls_mutex_free( &ctx->mutex );
72#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020073 mbedtls_aes_free( &ctx->aes_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050074 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Paul Bakkerfff03662014-06-18 16:21:25 +020075}
76
Hanno Beckera08651f2018-10-05 09:38:59 +010077void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx,
78 int resistance )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000079{
80 ctx->prediction_resistance = resistance;
81}
82
Hanno Beckera08651f2018-10-05 09:38:59 +010083void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx,
84 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000085{
86 ctx->entropy_len = len;
87}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +020088
Gilles Peskine9be50982019-10-22 18:42:27 +020089int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx,
90 size_t len )
91{
92 /* If mbedtls_ctr_drbg_seed() has already been called, it's
93 * too late. Return the error code that's closest to making sense. */
94 if( ctx->f_entropy != NULL )
95 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
96
97 if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
98 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
99#if SIZE_MAX > INT_MAX
100 /* This shouldn't be an issue because
101 * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible
102 * configuration, but make sure anyway. */
103 if( len > INT_MAX )
104 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
105#endif
106
107 /* For backward compatibility with Mbed TLS <= 2.19, store the
108 * entropy nonce length in a field that already exists, but isn't
109 * used until after the initial seeding. */
110 /* Due to the capping of len above, the value fits in an int. */
111 ctx->reseed_counter = (int) len;
112 return( 0 );
113}
114
Hanno Beckera08651f2018-10-05 09:38:59 +0100115void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx,
116 int interval )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000117{
118 ctx->reseed_interval = interval;
119}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200120
121static int block_cipher_df( unsigned char *output,
122 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000123{
Hanno Beckera08651f2018-10-05 09:38:59 +0100124 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
125 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200126 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
127 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
128 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100129 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200130 mbedtls_aes_context aes_ctx;
Dvir Markovich1b364992017-06-26 13:43:34 +0300131 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000132
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200133 int i, j;
134 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000135
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200136 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
137 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100138
Hanno Beckera08651f2018-10-05 09:38:59 +0100139 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
140 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200141 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000142
143 /*
144 * Construct IV (16 bytes) and S in buffer
145 * IV = Counter (in 32-bits) padded to 16 with zeroes
146 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
147 * data || 0x80
148 * (Total is padded to a multiple of 16-bytes with zeroes)
149 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200150 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000151 *p++ = ( data_len >> 24 ) & 0xff;
152 *p++ = ( data_len >> 16 ) & 0xff;
153 *p++ = ( data_len >> 8 ) & 0xff;
154 *p++ = ( data_len ) & 0xff;
155 p += 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200156 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000157 memcpy( p, data, data_len );
158 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000159
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200160 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000161
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200162 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000163 key[i] = i;
164
Hanno Beckera08651f2018-10-05 09:38:59 +0100165 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key,
166 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300167 {
168 goto exit;
169 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000170
171 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200172 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000173 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200174 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000175 {
176 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200177 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000178 use_len = buf_len;
179
180 while( use_len > 0 )
181 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200182 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000183 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200184 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
185 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
186 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000187
Hanno Beckera08651f2018-10-05 09:38:59 +0100188 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
189 chain, chain ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300190 {
191 goto exit;
192 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000193 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200194
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200195 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000196
197 /*
198 * Update IV
199 */
200 buf[3]++;
201 }
202
203 /*
204 * Do final encryption with reduced data
205 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100206 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp,
207 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300208 {
209 goto exit;
210 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200211 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000212 p = output;
213
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200214 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000215 {
Hanno Beckera08651f2018-10-05 09:38:59 +0100216 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
217 iv, iv ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300218 {
219 goto exit;
220 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200221 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
222 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000223 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300224exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200225 mbedtls_aes_free( &aes_ctx );
Dvir Markovich1b364992017-06-26 13:43:34 +0300226 /*
227 * tidy up the stack
228 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500229 mbedtls_platform_zeroize( buf, sizeof( buf ) );
230 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
231 mbedtls_platform_zeroize( key, sizeof( key ) );
232 mbedtls_platform_zeroize( chain, sizeof( chain ) );
Dvir Markovich1b364992017-06-26 13:43:34 +0300233 if( 0 != ret )
234 {
235 /*
236 * wipe partial seed from memory
237 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500238 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
Dvir Markovich1b364992017-06-26 13:43:34 +0300239 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200240
Dvir Markovich1b364992017-06-26 13:43:34 +0300241 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000242}
243
Gilles Peskineed7da592018-08-03 20:16:52 +0200244/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
245 * ctr_drbg_update_internal(ctx, provided_data)
246 * implements
247 * CTR_DRBG_Update(provided_data, Key, V)
248 * with inputs and outputs
249 * ctx->aes_ctx = Key
250 * ctx->counter = V
251 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200252static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
Hanno Beckera08651f2018-10-05 09:38:59 +0100253 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000254{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200255 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000256 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000257 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300258 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000259
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200260 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000261
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200262 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000263 {
264 /*
265 * Increase counter
266 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200267 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000268 if( ++ctx->counter[i - 1] != 0 )
269 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000270
271 /*
272 * Crypt counter block
273 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100274 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
275 ctx->counter, p ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300276 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200277 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300278 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000279
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200280 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000281 }
282
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200283 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000284 tmp[i] ^= data[i];
285
286 /*
287 * Update key and counter
288 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100289 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp,
290 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300291 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200292 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300293 }
Hanno Beckera08651f2018-10-05 09:38:59 +0100294 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
295 MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000296
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200297exit:
298 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
299 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000300}
301
Gilles Peskineed7da592018-08-03 20:16:52 +0200302/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
303 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
304 * implements
305 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
306 * security_strength) -> initial_working_state
307 * with inputs
308 * ctx->counter = all-bits-0
309 * ctx->aes_ctx = context from all-bits-0 key
310 * additional[:add_len] = entropy_input || nonce || personalization_string
311 * and with outputs
312 * ctx = initial_working_state
313 */
Gilles Peskined9199932018-09-11 16:41:54 +0200314int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
315 const unsigned char *additional,
316 size_t add_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000317{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200318 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Gilles Peskined9199932018-09-11 16:41:54 +0200319 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000320
Gilles Peskined9199932018-09-11 16:41:54 +0200321 if( add_len == 0 )
322 return( 0 );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100323
Gilles Peskined9199932018-09-11 16:41:54 +0200324 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
325 goto exit;
326 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
327 goto exit;
328
329exit:
330 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
331 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000332}
333
Gilles Peskined9199932018-09-11 16:41:54 +0200334#if !defined(MBEDTLS_DEPRECATED_REMOVED)
335void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
336 const unsigned char *additional,
337 size_t add_len )
338{
339 /* MAX_INPUT would be more logical here, but we have to match
340 * block_cipher_df()'s limits since we can't propagate errors */
341 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
342 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
343 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
344}
345#endif /* MBEDTLS_DEPRECATED_REMOVED */
346
Gilles Peskineed7da592018-08-03 20:16:52 +0200347/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
Gilles Peskine9be50982019-10-22 18:42:27 +0200348 * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
Gilles Peskineed7da592018-08-03 20:16:52 +0200349 * implements
350 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
351 * -> new_working_state
352 * with inputs
353 * ctx contains working_state
354 * additional[:len] = additional_input
355 * and entropy_input comes from calling ctx->f_entropy
Gilles Peskine9be50982019-10-22 18:42:27 +0200356 * for (ctx->entropy_len + nonce_len) bytes
Gilles Peskineed7da592018-08-03 20:16:52 +0200357 * and with output
358 * ctx contains new_working_state
359 */
Gilles Peskine9be50982019-10-22 18:42:27 +0200360int mbedtls_ctr_drbg_reseed_internal( mbedtls_ctr_drbg_context *ctx,
361 const unsigned char *additional,
362 size_t len,
363 size_t nonce_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000364{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200365 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000366 size_t seedlen = 0;
Dvir Markovich1b364992017-06-26 13:43:34 +0300367 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000368
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200369 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
370 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Gilles Peskine9be50982019-10-22 18:42:27 +0200371 if( nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
372 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
373 if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200374 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000375
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200376 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000377
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200378 /* Gather entropy_len bytes of entropy to seed state. */
379 if( 0 != ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000380 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200381 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000382 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000383 seedlen += ctx->entropy_len;
384
Gilles Peskine9be50982019-10-22 18:42:27 +0200385 /* Gather entropy for a nonce if requested. */
386 if( nonce_len != 0 )
387 {
388 if( 0 != ctx->f_entropy( ctx->p_entropy, seed, nonce_len ) )
389 {
390 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
391 }
392 seedlen += nonce_len;
393 }
394
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200395 /* Add additional data if provided. */
396 if( additional != NULL && len != 0 )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000397 {
398 memcpy( seed + seedlen, additional, len );
399 seedlen += len;
400 }
401
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200402 /* Reduce to 384 bits. */
Dvir Markovich1b364992017-06-26 13:43:34 +0300403 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200404 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000405
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200406 /* Update state. */
Dvir Markovich1b364992017-06-26 13:43:34 +0300407 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200408 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000409 ctx->reseed_counter = 1;
410
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200411exit:
412 mbedtls_platform_zeroize( seed, sizeof( seed ) );
413 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000414}
Paul Bakker9af723c2014-05-01 13:03:14 +0200415
Gilles Peskine9be50982019-10-22 18:42:27 +0200416int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
417 const unsigned char *additional, size_t len )
418{
419 return( mbedtls_ctr_drbg_reseed_internal( ctx, additional, len, 0 ) );
420}
421
Gilles Peskine8bf56132019-10-02 20:31:54 +0200422/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
Gilles Peskine379561f2019-10-18 16:57:48 +0200423 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
Gilles Peskine8bf56132019-10-02 20:31:54 +0200424 * implements
425 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
426 * security_strength) -> initial_working_state
427 * with inputs
428 * custom[:len] = nonce || personalization_string
Gilles Peskine379561f2019-10-18 16:57:48 +0200429 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
Gilles Peskine8bf56132019-10-02 20:31:54 +0200430 * and with outputs
431 * ctx = initial_working_state
432 */
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200433int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
434 int (*f_entropy)(void *, unsigned char *, size_t),
435 void *p_entropy,
436 const unsigned char *custom,
437 size_t len )
Gilles Peskine8bf56132019-10-02 20:31:54 +0200438{
439 int ret;
440 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
441
442 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
443
444 mbedtls_aes_init( &ctx->aes_ctx );
445
446 ctx->f_entropy = f_entropy;
447 ctx->p_entropy = p_entropy;
448
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200449 if( ctx->entropy_len == 0 )
450 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200451 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
452
Gilles Peskine9be50982019-10-22 18:42:27 +0200453 /* Initialize with an empty key. */
Gilles Peskine8bf56132019-10-02 20:31:54 +0200454 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
455 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
456 {
457 return( ret );
458 }
459
Gilles Peskine9be50982019-10-22 18:42:27 +0200460 /* Do the initial seeding.
461 * ctx->reseed_counter contains the desired amount of entropy to
462 * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()). */
463 if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len,
464 ctx->reseed_counter ) ) != 0 )
Gilles Peskine8bf56132019-10-02 20:31:54 +0200465 {
466 return( ret );
467 }
468 return( 0 );
469}
470
Gilles Peskineed7da592018-08-03 20:16:52 +0200471/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
472 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
473 * implements
474 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
475 * -> working_state_after_reseed
476 * if required, then
477 * CTR_DRBG_Generate(working_state_after_reseed,
478 * requested_number_of_bits, additional_input)
479 * -> status, returned_bits, new_working_state
480 * with inputs
481 * ctx contains working_state
482 * requested_number_of_bits = 8 * output_len
483 * additional[:add_len] = additional_input
484 * and entropy_input comes from calling ctx->f_entropy
485 * and with outputs
486 * status = SUCCESS (this function does the reseed internally)
487 * returned_bits = output[:output_len]
488 * ctx contains new_working_state
489 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200490int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000491 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000492 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000493{
494 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200495 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
496 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000497 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200498 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000499 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000500 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000501
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200502 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
503 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000504
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200505 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
506 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000507
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200508 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000509
510 if( ctx->reseed_counter > ctx->reseed_interval ||
511 ctx->prediction_resistance )
512 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200513 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300514 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000515 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300516 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000517 add_len = 0;
518 }
519
520 if( add_len > 0 )
521 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300522 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200523 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300524 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200525 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000526 }
527
528 while( output_len > 0 )
529 {
530 /*
531 * Increase counter
532 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200533 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000534 if( ++ctx->counter[i - 1] != 0 )
535 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000536
537 /*
538 * Crypt counter block
539 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100540 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
541 ctx->counter, tmp ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300542 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200543 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300544 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000545
Hanno Beckera08651f2018-10-05 09:38:59 +0100546 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE )
547 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000548 /*
549 * Copy random block to destination
550 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000551 memcpy( p, tmp, use_len );
552 p += use_len;
553 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000554 }
555
Dvir Markovich1b364992017-06-26 13:43:34 +0300556 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200557 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000558
559 ctx->reseed_counter++;
560
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200561exit:
562 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
563 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000564 return( 0 );
565}
566
Hanno Beckera08651f2018-10-05 09:38:59 +0100567int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output,
568 size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000569{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100570 int ret;
571 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
572
573#if defined(MBEDTLS_THREADING_C)
574 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
575 return( ret );
576#endif
577
578 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
579
580#if defined(MBEDTLS_THREADING_C)
581 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
582 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
583#endif
584
585 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000586}
587
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200588#if defined(MBEDTLS_FS_IO)
Hanno Beckera08651f2018-10-05 09:38:59 +0100589int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx,
590 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000591{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200592 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000593 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200594 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000595
596 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200597 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000598
Hanno Beckera08651f2018-10-05 09:38:59 +0100599 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf,
600 MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200601 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000602
Hanno Beckera08651f2018-10-05 09:38:59 +0100603 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) !=
604 MBEDTLS_CTR_DRBG_MAX_INPUT )
605 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200606 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Hanno Beckera08651f2018-10-05 09:38:59 +0100607 }
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100608 else
Hanno Beckera08651f2018-10-05 09:38:59 +0100609 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100610 ret = 0;
Hanno Beckera08651f2018-10-05 09:38:59 +0100611 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000612
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100613exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500614 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200615
Paul Bakkerfc754a92011-12-05 13:23:51 +0000616 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200617 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000618}
619
Hanno Beckera08651f2018-10-05 09:38:59 +0100620int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx,
621 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000622{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100623 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200624 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000625 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200626 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200627 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000628
629 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200630 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000631
Gilles Peskine82204662018-09-11 18:43:09 +0200632 n = fread( buf, 1, sizeof( buf ), f );
633 if( fread( &c, 1, 1, f ) != 0 )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100634 {
Gilles Peskine82204662018-09-11 18:43:09 +0200635 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
636 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100637 }
Gilles Peskine82204662018-09-11 18:43:09 +0200638 if( n == 0 || ferror( f ) )
639 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100640 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200641 goto exit;
642 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000643 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200644 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200645
Gilles Peskine82204662018-09-11 18:43:09 +0200646 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
647
648exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500649 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200650 if( f != NULL )
651 fclose( f );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100652 if( ret != 0 )
653 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200654 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000655}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200656#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000657
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200658#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000659
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000660static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000661 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
662 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
663 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
664 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
665 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
666 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
667 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
668 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
669 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
670 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
671 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
672 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
673
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000674static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000675 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
676 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
677 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
678 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
679 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
680 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
681 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
682 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
683
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100684static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000685 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
686 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
687
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100688static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000689 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
690 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
691
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100692static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000693 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
694 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
695
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100696static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000697 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
698 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
699
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100700static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200701static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
702 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000703{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100704 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000705 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100706 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000707 return( 0 );
708}
709
Paul Bakker7dc4c442014-02-01 22:50:26 +0100710#define CHK( c ) if( (c) != 0 ) \
711 { \
712 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200713 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100714 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100715 }
716
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000717/*
718 * Checkup routine
719 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200720int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000721{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200722 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000723 unsigned char buf[16];
724
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200725 mbedtls_ctr_drbg_init( &ctx );
726
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000727 /*
728 * Based on a NIST CTR_DRBG test vector (PR = True)
729 */
730 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200731 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000732
733 test_offset = 0;
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200734 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
735 CHK( mbedtls_ctr_drbg_seed( &ctx,
736 ctr_drbg_self_test_entropy,
737 (void *) entropy_source_pr,
738 nonce_pers_pr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200739 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
740 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
741 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
742 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000743
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100744 mbedtls_ctr_drbg_free( &ctx );
745
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000746 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200747 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000748
749 /*
750 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
751 */
752 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200753 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000754
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100755 mbedtls_ctr_drbg_init( &ctx );
756
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000757 test_offset = 0;
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200758 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
759 CHK( mbedtls_ctr_drbg_seed( &ctx,
760 ctr_drbg_self_test_entropy,
761 (void *) entropy_source_nopr,
762 nonce_pers_nopr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200763 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
764 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
765 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100766 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000767
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100768 mbedtls_ctr_drbg_free( &ctx );
769
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000770 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200771 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000772
773 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200774 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000775
776 return( 0 );
777}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200778#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000779
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200780#endif /* MBEDTLS_CTR_DRBG_C */