blob: e1900afc45599523b24ed66fc82b550dae5334b7 [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
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 * **********
45 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000046 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000047 */
48/*
Paul Sokolovsky8d6d8c82018-02-10 11:11:41 +020049 * The NIST SP 800-90 DRBGs are described in the following publication.
Paul Bakker0e04d0e2011-11-27 14:46:59 +000050 *
51 * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
52 */
53
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020054#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000055#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020056#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020057#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020058#endif
Paul Bakker0e04d0e2011-11-27 14:46:59 +000059
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020060#if defined(MBEDTLS_CTR_DRBG_C)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000061
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000062#include "mbedtls/ctr_drbg.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050063#include "mbedtls/platform_util.h"
Paul Bakker0e04d0e2011-11-27 14:46:59 +000064
Rich Evans00ab4702015-02-06 13:43:58 +000065#include <string.h>
66
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020067#if defined(MBEDTLS_FS_IO)
Paul Bakkerfc754a92011-12-05 13:23:51 +000068#include <stdio.h>
69#endif
70
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020071#if defined(MBEDTLS_SELF_TEST)
72#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000073#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010074#else
Rich Evans00ab4702015-02-06 13:43:58 +000075#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020076#define mbedtls_printf printf
77#endif /* MBEDTLS_PLATFORM_C */
78#endif /* MBEDTLS_SELF_TEST */
Paul Bakker7dc4c442014-02-01 22:50:26 +010079
Paul Bakker18d32912011-12-10 21:42:49 +000080/*
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020081 * CTR_DRBG context initialization
82 */
83void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
84{
85 memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010086
87#if defined(MBEDTLS_THREADING_C)
88 mbedtls_mutex_init( &ctx->mutex );
89#endif
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020090}
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)
98 mbedtls_mutex_free( &ctx->mutex );
99#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200100 mbedtls_aes_free( &ctx->aes_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500101 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Paul Bakkerfff03662014-06-18 16:21:25 +0200102}
103
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200104void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000105{
106 ctx->prediction_resistance = resistance;
107}
108
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200109void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000110{
111 ctx->entropy_len = len;
112}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200113
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200114void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000115{
116 ctx->reseed_interval = interval;
117}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200118
119static int block_cipher_df( unsigned char *output,
120 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000121{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200122 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
123 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
124 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
125 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100126 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200127 mbedtls_aes_context aes_ctx;
Dvir Markovich1b364992017-06-26 13:43:34 +0300128 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000129
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200130 int i, j;
131 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000132
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200133 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
134 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100135
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200136 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
137 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000138
139 /*
140 * Construct IV (16 bytes) and S in buffer
141 * IV = Counter (in 32-bits) padded to 16 with zeroes
142 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
143 * data || 0x80
144 * (Total is padded to a multiple of 16-bytes with zeroes)
145 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200146 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000147 *p++ = ( data_len >> 24 ) & 0xff;
148 *p++ = ( data_len >> 16 ) & 0xff;
149 *p++ = ( data_len >> 8 ) & 0xff;
150 *p++ = ( data_len ) & 0xff;
151 p += 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200152 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000153 memcpy( p, data, data_len );
154 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000155
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200156 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000157
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200158 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000159 key[i] = i;
160
Dvir Markovich1b364992017-06-26 13:43:34 +0300161 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
162 {
163 goto exit;
164 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000165
166 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200167 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000168 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200169 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000170 {
171 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200172 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000173 use_len = buf_len;
174
175 while( use_len > 0 )
176 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200177 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000178 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200179 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
180 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
181 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000182
Dvir Markovich1b364992017-06-26 13:43:34 +0300183 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ) ) != 0 )
184 {
185 goto exit;
186 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000187 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200188
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200189 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000190
191 /*
192 * Update IV
193 */
194 buf[3]++;
195 }
196
197 /*
198 * Do final encryption with reduced data
199 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300200 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
201 {
202 goto exit;
203 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200204 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000205 p = output;
206
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200207 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000208 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300209 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) ) != 0 )
210 {
211 goto exit;
212 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200213 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
214 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000215 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300216exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200217 mbedtls_aes_free( &aes_ctx );
Dvir Markovich1b364992017-06-26 13:43:34 +0300218 /*
219 * tidy up the stack
220 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500221 mbedtls_platform_zeroize( buf, sizeof( buf ) );
222 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
223 mbedtls_platform_zeroize( key, sizeof( key ) );
224 mbedtls_platform_zeroize( chain, sizeof( chain ) );
Dvir Markovich1b364992017-06-26 13:43:34 +0300225 if( 0 != ret )
226 {
227 /*
228 * wipe partial seed from memory
229 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500230 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
Dvir Markovich1b364992017-06-26 13:43:34 +0300231 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200232
Dvir Markovich1b364992017-06-26 13:43:34 +0300233 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000234}
235
Gilles Peskineed7da592018-08-03 20:16:52 +0200236/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
237 * ctr_drbg_update_internal(ctx, provided_data)
238 * implements
239 * CTR_DRBG_Update(provided_data, Key, V)
240 * with inputs and outputs
241 * ctx->aes_ctx = Key
242 * ctx->counter = V
243 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200244static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
245 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000246{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200247 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000248 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000249 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300250 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000251
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200252 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000253
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200254 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000255 {
256 /*
257 * Increase counter
258 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200259 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000260 if( ++ctx->counter[i - 1] != 0 )
261 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000262
263 /*
264 * Crypt counter block
265 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300266 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200267 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000268
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200269 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000270 }
271
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200272 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000273 tmp[i] ^= data[i];
274
275 /*
276 * Update key and counter
277 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300278 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200279 goto exit;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200280 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000281
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200282exit:
283 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
284 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000285}
286
Gilles Peskineed7da592018-08-03 20:16:52 +0200287/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
288 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
289 * implements
290 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
291 * security_strength) -> initial_working_state
292 * with inputs
293 * ctx->counter = all-bits-0
294 * ctx->aes_ctx = context from all-bits-0 key
295 * additional[:add_len] = entropy_input || nonce || personalization_string
296 * and with outputs
297 * ctx = initial_working_state
298 */
Gilles Peskined9199932018-09-11 16:41:54 +0200299int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
300 const unsigned char *additional,
301 size_t add_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000302{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200303 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Gilles Peskined9199932018-09-11 16:41:54 +0200304 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000305
Gilles Peskined9199932018-09-11 16:41:54 +0200306 if( add_len == 0 )
307 return( 0 );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100308
Gilles Peskined9199932018-09-11 16:41:54 +0200309 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
310 goto exit;
311 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
312 goto exit;
313
314exit:
315 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
316 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000317}
318
Gilles Peskined9199932018-09-11 16:41:54 +0200319#if !defined(MBEDTLS_DEPRECATED_REMOVED)
320void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
321 const unsigned char *additional,
322 size_t add_len )
323{
324 /* MAX_INPUT would be more logical here, but we have to match
325 * block_cipher_df()'s limits since we can't propagate errors */
326 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
327 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
328 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
329}
330#endif /* MBEDTLS_DEPRECATED_REMOVED */
331
Gilles Peskineed7da592018-08-03 20:16:52 +0200332/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
333 * mbedtls_ctr_drbg_reseed(ctx, additional, len)
334 * implements
335 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
336 * -> new_working_state
337 * with inputs
338 * ctx contains working_state
339 * additional[:len] = additional_input
340 * and entropy_input comes from calling ctx->f_entropy
341 * and with output
342 * ctx contains new_working_state
343 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200344int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000345 const unsigned char *additional, size_t len )
346{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200347 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000348 size_t seedlen = 0;
Dvir Markovich1b364992017-06-26 13:43:34 +0300349 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000350
Andres Amaya Garcia6a543362017-01-17 23:04:22 +0000351 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
352 len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200353 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000354
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200355 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000356
357 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200358 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000359 */
360 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
361 ctx->entropy_len ) )
362 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200363 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000364 }
365
366 seedlen += ctx->entropy_len;
367
368 /*
369 * Add additional data
370 */
371 if( additional && len )
372 {
373 memcpy( seed + seedlen, additional, len );
374 seedlen += len;
375 }
376
377 /*
378 * Reduce to 384 bits
379 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300380 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200381 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000382
383 /*
384 * Update state
385 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300386 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200387 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000388 ctx->reseed_counter = 1;
389
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200390exit:
391 mbedtls_platform_zeroize( seed, sizeof( seed ) );
392 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000393}
Paul Bakker9af723c2014-05-01 13:03:14 +0200394
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200395/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
Gilles Peskine912ffe42019-10-04 12:15:55 +0200396 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200397 * implements
398 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
399 * security_strength) -> initial_working_state
400 * with inputs
401 * custom[:len] = nonce || personalization_string
Gilles Peskine912ffe42019-10-04 12:15:55 +0200402 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200403 * and with outputs
404 * ctx = initial_working_state
405 */
Gilles Peskine912ffe42019-10-04 12:15:55 +0200406int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
407 int (*f_entropy)(void *, unsigned char *, size_t),
408 void *p_entropy,
409 const unsigned char *custom,
410 size_t len )
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200411{
412 int ret;
413 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
414
415 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
416
417 mbedtls_aes_init( &ctx->aes_ctx );
418
419 ctx->f_entropy = f_entropy;
420 ctx->p_entropy = p_entropy;
421
Gilles Peskine912ffe42019-10-04 12:15:55 +0200422 if( ctx->entropy_len == 0 )
423 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200424 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
425
426 /*
427 * Initialize with an empty key
428 */
429 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
430 {
431 return( ret );
432 }
433
434 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
435 {
436 return( ret );
437 }
438 return( 0 );
439}
440
Gilles Peskine912ffe42019-10-04 12:15:55 +0200441/* Backward compatibility wrapper */
442int mbedtls_ctr_drbg_seed_entropy_len(
443 mbedtls_ctr_drbg_context *ctx,
444 int (*f_entropy)(void *, unsigned char *, size_t), void *p_entropy,
445 const unsigned char *custom, size_t len,
446 size_t entropy_len )
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200447{
Gilles Peskine912ffe42019-10-04 12:15:55 +0200448 mbedtls_ctr_drbg_set_entropy_len( ctx, entropy_len );
449 return( mbedtls_ctr_drbg_seed( ctx, f_entropy, p_entropy, custom, len ) );
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200450}
451
Gilles Peskineed7da592018-08-03 20:16:52 +0200452/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
453 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
454 * implements
455 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
456 * -> working_state_after_reseed
457 * if required, then
458 * CTR_DRBG_Generate(working_state_after_reseed,
459 * requested_number_of_bits, additional_input)
460 * -> status, returned_bits, new_working_state
461 * with inputs
462 * ctx contains working_state
463 * requested_number_of_bits = 8 * output_len
464 * additional[:add_len] = additional_input
465 * and entropy_input comes from calling ctx->f_entropy
466 * and with outputs
467 * status = SUCCESS (this function does the reseed internally)
468 * returned_bits = output[:output_len]
469 * ctx contains new_working_state
470 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200471int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000472 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000473 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000474{
475 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200476 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
477 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000478 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200479 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000480 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000481 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000482
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200483 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
484 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000485
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200486 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
487 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000488
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200489 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000490
491 if( ctx->reseed_counter > ctx->reseed_interval ||
492 ctx->prediction_resistance )
493 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200494 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300495 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000496 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300497 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000498 add_len = 0;
499 }
500
501 if( add_len > 0 )
502 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300503 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200504 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300505 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200506 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000507 }
508
509 while( output_len > 0 )
510 {
511 /*
512 * Increase counter
513 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200514 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000515 if( ++ctx->counter[i - 1] != 0 )
516 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000517
518 /*
519 * Crypt counter block
520 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300521 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200522 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000523
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200524 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200525 output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000526 /*
527 * Copy random block to destination
528 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000529 memcpy( p, tmp, use_len );
530 p += use_len;
531 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000532 }
533
Dvir Markovich1b364992017-06-26 13:43:34 +0300534 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200535 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000536
537 ctx->reseed_counter++;
538
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200539exit:
540 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
541 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
Gilles Peskine86dd9502019-11-28 09:45:32 +0100542 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000543}
544
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200545int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000546{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100547 int ret;
548 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
549
550#if defined(MBEDTLS_THREADING_C)
551 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
552 return( ret );
553#endif
554
555 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
556
557#if defined(MBEDTLS_THREADING_C)
558 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
559 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
560#endif
561
562 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000563}
564
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200565#if defined(MBEDTLS_FS_IO)
566int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000567{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200568 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000569 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200570 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000571
572 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200573 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000574
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200575 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200576 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000577
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200578 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200579 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100580 else
581 ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000582
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100583exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500584 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200585
Paul Bakkerfc754a92011-12-05 13:23:51 +0000586 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200587 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000588}
589
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200590int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000591{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100592 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200593 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000594 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200595 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200596 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000597
598 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200599 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000600
Gilles Peskine82204662018-09-11 18:43:09 +0200601 n = fread( buf, 1, sizeof( buf ), f );
602 if( fread( &c, 1, 1, f ) != 0 )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100603 {
Gilles Peskine82204662018-09-11 18:43:09 +0200604 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
605 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100606 }
Gilles Peskine82204662018-09-11 18:43:09 +0200607 if( n == 0 || ferror( f ) )
608 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100609 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200610 goto exit;
611 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000612 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200613 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200614
Gilles Peskine82204662018-09-11 18:43:09 +0200615 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
616
617exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500618 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200619 if( f != NULL )
620 fclose( f );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100621 if( ret != 0 )
622 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200623 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000624}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200625#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000626
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200627#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000628
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000629static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000630 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
631 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
632 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
633 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
634 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
635 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
636 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
637 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
638 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
639 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
640 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
641 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
642
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000643static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000644 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
645 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
646 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
647 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
648 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
649 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
650 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
651 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
652
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100653static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000654 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
655 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
656
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100657static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000658 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
659 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
660
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100661static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000662 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
663 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
664
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100665static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000666 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
667 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
668
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100669static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200670static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
671 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000672{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100673 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000674 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100675 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000676 return( 0 );
677}
678
Paul Bakker7dc4c442014-02-01 22:50:26 +0100679#define CHK( c ) if( (c) != 0 ) \
680 { \
681 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200682 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100683 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100684 }
685
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000686/*
687 * Checkup routine
688 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200689int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000690{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200691 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000692 unsigned char buf[16];
693
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200694 mbedtls_ctr_drbg_init( &ctx );
695
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000696 /*
697 * Based on a NIST CTR_DRBG test vector (PR = True)
698 */
699 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200700 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000701
702 test_offset = 0;
Gilles Peskine912ffe42019-10-04 12:15:55 +0200703 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
704 CHK( mbedtls_ctr_drbg_seed( &ctx,
705 ctr_drbg_self_test_entropy,
706 (void *) entropy_source_pr,
707 nonce_pers_pr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200708 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
709 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
710 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
711 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000712
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100713 mbedtls_ctr_drbg_free( &ctx );
714
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000715 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200716 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000717
718 /*
719 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
720 */
721 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200722 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000723
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100724 mbedtls_ctr_drbg_init( &ctx );
725
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000726 test_offset = 0;
Gilles Peskine912ffe42019-10-04 12:15:55 +0200727 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
728 CHK( mbedtls_ctr_drbg_seed( &ctx,
729 ctr_drbg_self_test_entropy,
730 (void *) entropy_source_nopr,
731 nonce_pers_nopr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200732 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
733 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
734 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100735 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000736
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100737 mbedtls_ctr_drbg_free( &ctx );
738
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000739 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200740 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000741
742 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200743 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000744
745 return( 0 );
746}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200747#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000748
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200749#endif /* MBEDTLS_CTR_DRBG_C */