blob: 5461b71214dd644d2bf16097b0b0aa94a047d738 [file] [log] [blame]
Paul Bakker0e04d0e2011-11-27 14:46:59 +00001/*
2 * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
3 *
Bence Szépkútia2947ac2020-08-19 16:37:36 +02004 * Copyright The Mbed TLS Contributors
Bence Szépkútif744bd72020-06-05 13:02:18 +02005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6 *
7 * This file is provided under the Apache License 2.0, or the
8 * GNU General Public License v2.0 or later.
9 *
10 * **********
11 * Apache License 2.0:
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +020012 *
13 * Licensed under the Apache License, Version 2.0 (the "License"); you may
14 * not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 * http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
21 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
Paul Bakker0e04d0e2011-11-27 14:46:59 +000024 *
Bence Szépkútif744bd72020-06-05 13:02:18 +020025 * **********
26 *
27 * **********
28 * GNU General Public License v2.0 or later:
29 *
30 * This program is free software; you can redistribute it and/or modify
31 * it under the terms of the GNU General Public License as published by
32 * the Free Software Foundation; either version 2 of the License, or
33 * (at your option) any later version.
34 *
35 * This program is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
39 *
40 * You should have received a copy of the GNU General Public License along
41 * with this program; if not, write to the Free Software Foundation, Inc.,
42 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
43 *
44 * **********
Paul Bakker0e04d0e2011-11-27 14:46:59 +000045 */
46/*
Paul Sokolovsky8d6d8c82018-02-10 11:11:41 +020047 * The NIST SP 800-90 DRBGs are described in the following publication.
Paul Bakker0e04d0e2011-11-27 14:46:59 +000048 *
49 * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
50 */
51
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020052#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000053#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020054#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020055#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020056#endif
Paul Bakker0e04d0e2011-11-27 14:46:59 +000057
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020058#if defined(MBEDTLS_CTR_DRBG_C)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000059
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000060#include "mbedtls/ctr_drbg.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050061#include "mbedtls/platform_util.h"
Paul Bakker0e04d0e2011-11-27 14:46:59 +000062
Rich Evans00ab4702015-02-06 13:43:58 +000063#include <string.h>
64
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020065#if defined(MBEDTLS_FS_IO)
Paul Bakkerfc754a92011-12-05 13:23:51 +000066#include <stdio.h>
67#endif
68
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020069#if defined(MBEDTLS_SELF_TEST)
70#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000071#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010072#else
Rich Evans00ab4702015-02-06 13:43:58 +000073#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020074#define mbedtls_printf printf
75#endif /* MBEDTLS_PLATFORM_C */
76#endif /* MBEDTLS_SELF_TEST */
Paul Bakker7dc4c442014-02-01 22:50:26 +010077
Paul Bakker18d32912011-12-10 21:42:49 +000078/*
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020079 * CTR_DRBG context initialization
80 */
81void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
82{
83 memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010084
Gavin Acquroff77cb30c2020-03-01 17:06:11 -080085 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020086}
87
Gavin Acquroff77cb30c2020-03-01 17:06:11 -080088/*
89 * This function resets CTR_DRBG context to the state immediately
90 * after initial call of mbedtls_ctr_drbg_init().
91 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020092void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
Paul Bakkerfff03662014-06-18 16:21:25 +020093{
94 if( ctx == NULL )
95 return;
96
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010097#if defined(MBEDTLS_THREADING_C)
Gilles Peskine89816bc2021-01-30 13:05:32 +010098 if( ctx->f_entropy != NULL )
99 mbedtls_mutex_free( &ctx->mutex );
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100100#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200101 mbedtls_aes_free( &ctx->aes_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500102 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Gavin Acquroff77cb30c2020-03-01 17:06:11 -0800103 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
Paul Bakkerfff03662014-06-18 16:21:25 +0200104}
105
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200106void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000107{
108 ctx->prediction_resistance = resistance;
109}
110
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200111void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000112{
113 ctx->entropy_len = len;
114}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200115
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200116void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, 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{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200124 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
125 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
126 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
127 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100128 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200129 mbedtls_aes_context aes_ctx;
Dvir Markovich1b364992017-06-26 13:43:34 +0300130 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000131
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200132 int i, j;
133 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000134
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200135 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
136 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100137
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200138 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
139 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000140
141 /*
142 * Construct IV (16 bytes) and S in buffer
143 * IV = Counter (in 32-bits) padded to 16 with zeroes
144 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
145 * data || 0x80
146 * (Total is padded to a multiple of 16-bytes with zeroes)
147 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200148 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000149 *p++ = ( data_len >> 24 ) & 0xff;
150 *p++ = ( data_len >> 16 ) & 0xff;
151 *p++ = ( data_len >> 8 ) & 0xff;
152 *p++ = ( data_len ) & 0xff;
153 p += 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200154 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000155 memcpy( p, data, data_len );
156 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000157
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200158 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000159
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200160 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000161 key[i] = i;
162
Dvir Markovich1b364992017-06-26 13:43:34 +0300163 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
164 {
165 goto exit;
166 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000167
168 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200169 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000170 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200171 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000172 {
173 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200174 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000175 use_len = buf_len;
176
177 while( use_len > 0 )
178 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200179 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000180 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200181 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
182 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
183 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000184
Dvir Markovich1b364992017-06-26 13:43:34 +0300185 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ) ) != 0 )
186 {
187 goto exit;
188 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000189 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200190
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200191 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000192
193 /*
194 * Update IV
195 */
196 buf[3]++;
197 }
198
199 /*
200 * Do final encryption with reduced data
201 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300202 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
203 {
204 goto exit;
205 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200206 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000207 p = output;
208
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200209 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000210 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300211 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) ) != 0 )
212 {
213 goto exit;
214 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200215 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
216 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000217 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300218exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200219 mbedtls_aes_free( &aes_ctx );
Dvir Markovich1b364992017-06-26 13:43:34 +0300220 /*
221 * tidy up the stack
222 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500223 mbedtls_platform_zeroize( buf, sizeof( buf ) );
224 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
225 mbedtls_platform_zeroize( key, sizeof( key ) );
226 mbedtls_platform_zeroize( chain, sizeof( chain ) );
Dvir Markovich1b364992017-06-26 13:43:34 +0300227 if( 0 != ret )
228 {
229 /*
230 * wipe partial seed from memory
231 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500232 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
Dvir Markovich1b364992017-06-26 13:43:34 +0300233 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200234
Dvir Markovich1b364992017-06-26 13:43:34 +0300235 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000236}
237
Gilles Peskineed7da592018-08-03 20:16:52 +0200238/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
239 * ctr_drbg_update_internal(ctx, provided_data)
240 * implements
241 * CTR_DRBG_Update(provided_data, Key, V)
242 * with inputs and outputs
243 * ctx->aes_ctx = Key
244 * ctx->counter = V
245 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200246static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
247 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000248{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200249 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000250 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000251 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300252 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000253
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200254 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000255
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200256 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000257 {
258 /*
259 * Increase counter
260 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200261 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000262 if( ++ctx->counter[i - 1] != 0 )
263 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000264
265 /*
266 * Crypt counter block
267 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300268 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200269 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000270
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200271 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000272 }
273
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200274 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000275 tmp[i] ^= data[i];
276
277 /*
278 * Update key and counter
279 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300280 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200281 goto exit;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200282 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000283
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200284exit:
285 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
286 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000287}
288
Gilles Peskineed7da592018-08-03 20:16:52 +0200289/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
290 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
291 * implements
292 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
293 * security_strength) -> initial_working_state
294 * with inputs
295 * ctx->counter = all-bits-0
296 * ctx->aes_ctx = context from all-bits-0 key
297 * additional[:add_len] = entropy_input || nonce || personalization_string
298 * and with outputs
299 * ctx = initial_working_state
300 */
Gilles Peskined9199932018-09-11 16:41:54 +0200301int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
302 const unsigned char *additional,
303 size_t add_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000304{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200305 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Gilles Peskined9199932018-09-11 16:41:54 +0200306 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000307
Gilles Peskined9199932018-09-11 16:41:54 +0200308 if( add_len == 0 )
309 return( 0 );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100310
Gilles Peskined9199932018-09-11 16:41:54 +0200311 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
312 goto exit;
313 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
314 goto exit;
315
316exit:
317 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
318 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000319}
320
Gilles Peskined9199932018-09-11 16:41:54 +0200321#if !defined(MBEDTLS_DEPRECATED_REMOVED)
322void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
323 const unsigned char *additional,
324 size_t add_len )
325{
326 /* MAX_INPUT would be more logical here, but we have to match
327 * block_cipher_df()'s limits since we can't propagate errors */
328 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
329 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
330 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
331}
332#endif /* MBEDTLS_DEPRECATED_REMOVED */
333
Gilles Peskineed7da592018-08-03 20:16:52 +0200334/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
335 * mbedtls_ctr_drbg_reseed(ctx, additional, len)
336 * implements
337 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
338 * -> new_working_state
339 * with inputs
340 * ctx contains working_state
341 * additional[:len] = additional_input
342 * and entropy_input comes from calling ctx->f_entropy
343 * and with output
344 * ctx contains new_working_state
345 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200346int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000347 const unsigned char *additional, size_t len )
348{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200349 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000350 size_t seedlen = 0;
Dvir Markovich1b364992017-06-26 13:43:34 +0300351 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000352
Andres Amaya Garcia6a543362017-01-17 23:04:22 +0000353 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
354 len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200355 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000356
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200357 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000358
359 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200360 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000361 */
362 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
363 ctx->entropy_len ) )
364 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200365 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000366 }
367
368 seedlen += ctx->entropy_len;
369
370 /*
371 * Add additional data
372 */
373 if( additional && len )
374 {
375 memcpy( seed + seedlen, additional, len );
376 seedlen += len;
377 }
378
379 /*
380 * Reduce to 384 bits
381 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300382 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200383 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000384
385 /*
386 * Update state
387 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300388 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200389 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000390 ctx->reseed_counter = 1;
391
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200392exit:
393 mbedtls_platform_zeroize( seed, sizeof( seed ) );
394 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000395}
Paul Bakker9af723c2014-05-01 13:03:14 +0200396
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200397/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
Gilles Peskine912ffe42019-10-04 12:15:55 +0200398 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200399 * implements
400 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
401 * security_strength) -> initial_working_state
402 * with inputs
403 * custom[:len] = nonce || personalization_string
Gilles Peskine912ffe42019-10-04 12:15:55 +0200404 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200405 * and with outputs
406 * ctx = initial_working_state
407 */
Gilles Peskine912ffe42019-10-04 12:15:55 +0200408int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
409 int (*f_entropy)(void *, unsigned char *, size_t),
410 void *p_entropy,
411 const unsigned char *custom,
412 size_t len )
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200413{
414 int ret;
415 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
416
417 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
418
Gilles Peskine89816bc2021-01-30 13:05:32 +0100419#if defined(MBEDTLS_THREADING_C)
420 mbedtls_mutex_init( &ctx->mutex );
421#endif
422
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200423 mbedtls_aes_init( &ctx->aes_ctx );
424
425 ctx->f_entropy = f_entropy;
426 ctx->p_entropy = p_entropy;
427
Gilles Peskine912ffe42019-10-04 12:15:55 +0200428 if( ctx->entropy_len == 0 )
429 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200430
431 /*
432 * Initialize with an empty key
433 */
434 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
435 {
436 return( ret );
437 }
438
439 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
440 {
441 return( ret );
442 }
443 return( 0 );
444}
445
Gilles Peskine912ffe42019-10-04 12:15:55 +0200446/* Backward compatibility wrapper */
447int mbedtls_ctr_drbg_seed_entropy_len(
448 mbedtls_ctr_drbg_context *ctx,
449 int (*f_entropy)(void *, unsigned char *, size_t), void *p_entropy,
450 const unsigned char *custom, size_t len,
451 size_t entropy_len )
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200452{
Gilles Peskine912ffe42019-10-04 12:15:55 +0200453 mbedtls_ctr_drbg_set_entropy_len( ctx, entropy_len );
454 return( mbedtls_ctr_drbg_seed( ctx, f_entropy, p_entropy, custom, len ) );
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200455}
456
Gilles Peskineed7da592018-08-03 20:16:52 +0200457/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
458 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
459 * implements
460 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
461 * -> working_state_after_reseed
462 * if required, then
463 * CTR_DRBG_Generate(working_state_after_reseed,
464 * requested_number_of_bits, additional_input)
465 * -> status, returned_bits, new_working_state
466 * with inputs
467 * ctx contains working_state
468 * requested_number_of_bits = 8 * output_len
469 * additional[:add_len] = additional_input
470 * and entropy_input comes from calling ctx->f_entropy
471 * and with outputs
472 * status = SUCCESS (this function does the reseed internally)
473 * returned_bits = output[:output_len]
474 * ctx contains new_working_state
475 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200476int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000477 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000478 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000479{
480 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
482 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000483 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200484 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000485 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000486 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000487
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200488 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
489 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000490
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200491 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
492 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000493
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200494 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000495
496 if( ctx->reseed_counter > ctx->reseed_interval ||
497 ctx->prediction_resistance )
498 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200499 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300500 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000501 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300502 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000503 add_len = 0;
504 }
505
506 if( add_len > 0 )
507 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300508 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200509 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300510 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200511 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000512 }
513
514 while( output_len > 0 )
515 {
516 /*
517 * Increase counter
518 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200519 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000520 if( ++ctx->counter[i - 1] != 0 )
521 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000522
523 /*
524 * Crypt counter block
525 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300526 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200527 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000528
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200529 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200530 output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000531 /*
532 * Copy random block to destination
533 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000534 memcpy( p, tmp, use_len );
535 p += use_len;
536 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000537 }
538
Dvir Markovich1b364992017-06-26 13:43:34 +0300539 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200540 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000541
542 ctx->reseed_counter++;
543
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200544exit:
545 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
546 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
Gilles Peskine86dd9502019-11-28 09:45:32 +0100547 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000548}
549
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200550int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000551{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100552 int ret;
553 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
554
555#if defined(MBEDTLS_THREADING_C)
556 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
557 return( ret );
558#endif
559
560 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
561
562#if defined(MBEDTLS_THREADING_C)
563 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
564 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
565#endif
566
567 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000568}
569
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200570#if defined(MBEDTLS_FS_IO)
571int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000572{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200573 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000574 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200575 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000576
577 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200578 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000579
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200580 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200581 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000582
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200583 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200584 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100585 else
586 ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000587
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100588exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500589 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200590
Paul Bakkerfc754a92011-12-05 13:23:51 +0000591 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200592 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000593}
594
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200595int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000596{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100597 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200598 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000599 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200600 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200601 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000602
603 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200604 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000605
Gilles Peskine82204662018-09-11 18:43:09 +0200606 n = fread( buf, 1, sizeof( buf ), f );
607 if( fread( &c, 1, 1, f ) != 0 )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100608 {
Gilles Peskine82204662018-09-11 18:43:09 +0200609 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
610 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100611 }
Gilles Peskine82204662018-09-11 18:43:09 +0200612 if( n == 0 || ferror( f ) )
613 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100614 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200615 goto exit;
616 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000617 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200618 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200619
Gilles Peskine82204662018-09-11 18:43:09 +0200620 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
621
622exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500623 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200624 if( f != NULL )
625 fclose( f );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100626 if( ret != 0 )
627 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200628 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000629}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200630#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000631
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200632#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000633
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000634static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000635 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
636 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
637 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
638 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
639 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
640 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
641 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
642 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
643 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
644 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
645 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
646 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
647
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000648static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000649 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
650 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
651 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
652 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
653 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
654 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
655 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
656 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
657
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100658static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000659 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
660 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
661
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100662static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000663 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
664 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
665
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100666static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000667 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
668 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
669
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100670static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000671 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
672 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
673
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100674static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200675static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
676 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000677{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100678 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000679 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100680 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000681 return( 0 );
682}
683
Paul Bakker7dc4c442014-02-01 22:50:26 +0100684#define CHK( c ) if( (c) != 0 ) \
685 { \
686 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200687 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100688 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100689 }
690
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000691/*
692 * Checkup routine
693 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200694int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000695{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200696 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000697 unsigned char buf[16];
698
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200699 mbedtls_ctr_drbg_init( &ctx );
700
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000701 /*
702 * Based on a NIST CTR_DRBG test vector (PR = True)
703 */
704 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200705 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000706
707 test_offset = 0;
Gilles Peskine912ffe42019-10-04 12:15:55 +0200708 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
709 CHK( mbedtls_ctr_drbg_seed( &ctx,
710 ctr_drbg_self_test_entropy,
711 (void *) entropy_source_pr,
712 nonce_pers_pr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200713 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
714 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
715 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
716 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000717
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100718 mbedtls_ctr_drbg_free( &ctx );
719
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000720 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200721 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000722
723 /*
724 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
725 */
726 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200727 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000728
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100729 mbedtls_ctr_drbg_init( &ctx );
730
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000731 test_offset = 0;
Gilles Peskine912ffe42019-10-04 12:15:55 +0200732 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
733 CHK( mbedtls_ctr_drbg_seed( &ctx,
734 ctr_drbg_self_test_entropy,
735 (void *) entropy_source_nopr,
736 nonce_pers_nopr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200737 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
738 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
739 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100740 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000741
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100742 mbedtls_ctr_drbg_free( &ctx );
743
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000744 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200745 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000746
747 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200748 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000749
750 return( 0 );
751}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200752#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000753
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200754#endif /* MBEDTLS_CTR_DRBG_C */