blob: ae51d546791595b8317a84dfddb71bf4ce2f6a14 [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
Hanno Beckera08651f2018-10-05 09:38:59 +010089void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx,
90 int interval )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000091{
92 ctx->reseed_interval = interval;
93}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +020094
95static int block_cipher_df( unsigned char *output,
96 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000097{
Hanno Beckera08651f2018-10-05 09:38:59 +010098 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
99 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200100 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
101 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
102 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100103 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200104 mbedtls_aes_context aes_ctx;
Dvir Markovich1b364992017-06-26 13:43:34 +0300105 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000106
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200107 int i, j;
108 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000109
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200110 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
111 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100112
Hanno Beckera08651f2018-10-05 09:38:59 +0100113 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
114 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200115 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000116
117 /*
118 * Construct IV (16 bytes) and S in buffer
119 * IV = Counter (in 32-bits) padded to 16 with zeroes
120 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
121 * data || 0x80
122 * (Total is padded to a multiple of 16-bytes with zeroes)
123 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200124 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000125 *p++ = ( data_len >> 24 ) & 0xff;
126 *p++ = ( data_len >> 16 ) & 0xff;
127 *p++ = ( data_len >> 8 ) & 0xff;
128 *p++ = ( data_len ) & 0xff;
129 p += 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200130 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000131 memcpy( p, data, data_len );
132 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000133
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200134 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000135
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200136 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000137 key[i] = i;
138
Hanno Beckera08651f2018-10-05 09:38:59 +0100139 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key,
140 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300141 {
142 goto exit;
143 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000144
145 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200146 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000147 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200148 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000149 {
150 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200151 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000152 use_len = buf_len;
153
154 while( use_len > 0 )
155 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200156 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000157 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200158 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
159 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
160 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000161
Hanno Beckera08651f2018-10-05 09:38:59 +0100162 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
163 chain, chain ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300164 {
165 goto exit;
166 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000167 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200168
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200169 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000170
171 /*
172 * Update IV
173 */
174 buf[3]++;
175 }
176
177 /*
178 * Do final encryption with reduced data
179 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100180 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp,
181 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300182 {
183 goto exit;
184 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200185 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000186 p = output;
187
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200188 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000189 {
Hanno Beckera08651f2018-10-05 09:38:59 +0100190 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
191 iv, iv ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300192 {
193 goto exit;
194 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200195 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
196 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000197 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300198exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200199 mbedtls_aes_free( &aes_ctx );
Dvir Markovich1b364992017-06-26 13:43:34 +0300200 /*
201 * tidy up the stack
202 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500203 mbedtls_platform_zeroize( buf, sizeof( buf ) );
204 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
205 mbedtls_platform_zeroize( key, sizeof( key ) );
206 mbedtls_platform_zeroize( chain, sizeof( chain ) );
Dvir Markovich1b364992017-06-26 13:43:34 +0300207 if( 0 != ret )
208 {
209 /*
210 * wipe partial seed from memory
211 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500212 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
Dvir Markovich1b364992017-06-26 13:43:34 +0300213 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200214
Dvir Markovich1b364992017-06-26 13:43:34 +0300215 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000216}
217
Gilles Peskineed7da592018-08-03 20:16:52 +0200218/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
219 * ctr_drbg_update_internal(ctx, provided_data)
220 * implements
221 * CTR_DRBG_Update(provided_data, Key, V)
222 * with inputs and outputs
223 * ctx->aes_ctx = Key
224 * ctx->counter = V
225 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200226static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
Hanno Beckera08651f2018-10-05 09:38:59 +0100227 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000228{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200229 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000230 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000231 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300232 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000233
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200234 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000235
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200236 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000237 {
238 /*
239 * Increase counter
240 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200241 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000242 if( ++ctx->counter[i - 1] != 0 )
243 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000244
245 /*
246 * Crypt counter block
247 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100248 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
249 ctx->counter, p ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300250 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200251 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300252 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000253
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200254 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000255 }
256
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200257 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000258 tmp[i] ^= data[i];
259
260 /*
261 * Update key and counter
262 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100263 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp,
264 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300265 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200266 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300267 }
Hanno Beckera08651f2018-10-05 09:38:59 +0100268 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
269 MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000270
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200271exit:
272 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
273 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000274}
275
Gilles Peskineed7da592018-08-03 20:16:52 +0200276/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
277 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
278 * implements
279 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
280 * security_strength) -> initial_working_state
281 * with inputs
282 * ctx->counter = all-bits-0
283 * ctx->aes_ctx = context from all-bits-0 key
284 * additional[:add_len] = entropy_input || nonce || personalization_string
285 * and with outputs
286 * ctx = initial_working_state
287 */
Gilles Peskined9199932018-09-11 16:41:54 +0200288int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
289 const unsigned char *additional,
290 size_t add_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000291{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200292 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Gilles Peskined9199932018-09-11 16:41:54 +0200293 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000294
Gilles Peskined9199932018-09-11 16:41:54 +0200295 if( add_len == 0 )
296 return( 0 );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100297
Gilles Peskined9199932018-09-11 16:41:54 +0200298 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
299 goto exit;
300 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
301 goto exit;
302
303exit:
304 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
305 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000306}
307
Gilles Peskined9199932018-09-11 16:41:54 +0200308#if !defined(MBEDTLS_DEPRECATED_REMOVED)
309void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
310 const unsigned char *additional,
311 size_t add_len )
312{
313 /* MAX_INPUT would be more logical here, but we have to match
314 * block_cipher_df()'s limits since we can't propagate errors */
315 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
316 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
317 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
318}
319#endif /* MBEDTLS_DEPRECATED_REMOVED */
320
Gilles Peskineed7da592018-08-03 20:16:52 +0200321/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
322 * mbedtls_ctr_drbg_reseed(ctx, additional, len)
323 * implements
324 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
325 * -> new_working_state
326 * with inputs
327 * ctx contains working_state
328 * additional[:len] = additional_input
329 * and entropy_input comes from calling ctx->f_entropy
330 * and with output
331 * ctx contains new_working_state
332 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200333int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000334 const unsigned char *additional, size_t len )
335{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200336 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000337 size_t seedlen = 0;
Dvir Markovich1b364992017-06-26 13:43:34 +0300338 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000339
Andres Amaya Garcia6a543362017-01-17 23:04:22 +0000340 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
341 len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200342 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000343
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200344 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000345
346 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200347 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000348 */
349 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
350 ctx->entropy_len ) )
351 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200352 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000353 }
354
355 seedlen += ctx->entropy_len;
356
357 /*
358 * Add additional data
359 */
360 if( additional && len )
361 {
362 memcpy( seed + seedlen, additional, len );
363 seedlen += len;
364 }
365
366 /*
367 * Reduce to 384 bits
368 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300369 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200370 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000371
372 /*
373 * Update state
374 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300375 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200376 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000377 ctx->reseed_counter = 1;
378
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200379exit:
380 mbedtls_platform_zeroize( seed, sizeof( seed ) );
381 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000382}
Paul Bakker9af723c2014-05-01 13:03:14 +0200383
Gilles Peskine8bf56132019-10-02 20:31:54 +0200384/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
385 * mbedtls_ctr_drbg_seed_entropy_len(ctx, f_entropy, p_entropy,
386 * custom, len, entropy_len)
387 * implements
388 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
389 * security_strength) -> initial_working_state
390 * with inputs
391 * custom[:len] = nonce || personalization_string
392 * where entropy_input comes from f_entropy for entropy_len bytes
393 * and with outputs
394 * ctx = initial_working_state
395 */
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200396int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
397 int (*f_entropy)(void *, unsigned char *, size_t),
398 void *p_entropy,
399 const unsigned char *custom,
400 size_t len )
Gilles Peskine8bf56132019-10-02 20:31:54 +0200401{
402 int ret;
403 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
404
405 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
406
407 mbedtls_aes_init( &ctx->aes_ctx );
408
409 ctx->f_entropy = f_entropy;
410 ctx->p_entropy = p_entropy;
411
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200412 if( ctx->entropy_len == 0 )
413 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200414 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
415
416 /*
417 * Initialize with an empty key
418 */
419 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
420 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
421 {
422 return( ret );
423 }
424
425 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
426 {
427 return( ret );
428 }
429 return( 0 );
430}
431
Gilles Peskineed7da592018-08-03 20:16:52 +0200432/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
433 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
434 * implements
435 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
436 * -> working_state_after_reseed
437 * if required, then
438 * CTR_DRBG_Generate(working_state_after_reseed,
439 * requested_number_of_bits, additional_input)
440 * -> status, returned_bits, new_working_state
441 * with inputs
442 * ctx contains working_state
443 * requested_number_of_bits = 8 * output_len
444 * additional[:add_len] = additional_input
445 * and entropy_input comes from calling ctx->f_entropy
446 * and with outputs
447 * status = SUCCESS (this function does the reseed internally)
448 * returned_bits = output[:output_len]
449 * ctx contains new_working_state
450 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200451int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000452 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000453 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000454{
455 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200456 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
457 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000458 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200459 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000460 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000461 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000462
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200463 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
464 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000465
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200466 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
467 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000468
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200469 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000470
471 if( ctx->reseed_counter > ctx->reseed_interval ||
472 ctx->prediction_resistance )
473 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200474 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300475 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000476 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300477 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000478 add_len = 0;
479 }
480
481 if( add_len > 0 )
482 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300483 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200484 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300485 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200486 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000487 }
488
489 while( output_len > 0 )
490 {
491 /*
492 * Increase counter
493 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200494 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000495 if( ++ctx->counter[i - 1] != 0 )
496 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000497
498 /*
499 * Crypt counter block
500 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100501 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
502 ctx->counter, tmp ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300503 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200504 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300505 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000506
Hanno Beckera08651f2018-10-05 09:38:59 +0100507 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE )
508 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000509 /*
510 * Copy random block to destination
511 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000512 memcpy( p, tmp, use_len );
513 p += use_len;
514 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000515 }
516
Dvir Markovich1b364992017-06-26 13:43:34 +0300517 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200518 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000519
520 ctx->reseed_counter++;
521
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200522exit:
523 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
524 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000525 return( 0 );
526}
527
Hanno Beckera08651f2018-10-05 09:38:59 +0100528int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output,
529 size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000530{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100531 int ret;
532 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
533
534#if defined(MBEDTLS_THREADING_C)
535 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
536 return( ret );
537#endif
538
539 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
540
541#if defined(MBEDTLS_THREADING_C)
542 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
543 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
544#endif
545
546 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000547}
548
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200549#if defined(MBEDTLS_FS_IO)
Hanno Beckera08651f2018-10-05 09:38:59 +0100550int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx,
551 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000552{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200553 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000554 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200555 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000556
557 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200558 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000559
Hanno Beckera08651f2018-10-05 09:38:59 +0100560 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf,
561 MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200562 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000563
Hanno Beckera08651f2018-10-05 09:38:59 +0100564 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) !=
565 MBEDTLS_CTR_DRBG_MAX_INPUT )
566 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200567 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Hanno Beckera08651f2018-10-05 09:38:59 +0100568 }
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100569 else
Hanno Beckera08651f2018-10-05 09:38:59 +0100570 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100571 ret = 0;
Hanno Beckera08651f2018-10-05 09:38:59 +0100572 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000573
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100574exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500575 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200576
Paul Bakkerfc754a92011-12-05 13:23:51 +0000577 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200578 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000579}
580
Hanno Beckera08651f2018-10-05 09:38:59 +0100581int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx,
582 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000583{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100584 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200585 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000586 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200587 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200588 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000589
590 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200591 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000592
Gilles Peskine82204662018-09-11 18:43:09 +0200593 n = fread( buf, 1, sizeof( buf ), f );
594 if( fread( &c, 1, 1, f ) != 0 )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100595 {
Gilles Peskine82204662018-09-11 18:43:09 +0200596 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
597 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100598 }
Gilles Peskine82204662018-09-11 18:43:09 +0200599 if( n == 0 || ferror( f ) )
600 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100601 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200602 goto exit;
603 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000604 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200605 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200606
Gilles Peskine82204662018-09-11 18:43:09 +0200607 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
608
609exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500610 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200611 if( f != NULL )
612 fclose( f );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100613 if( ret != 0 )
614 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200615 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000616}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200617#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000618
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200619#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000620
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000621static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000622 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
623 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
624 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
625 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
626 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
627 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
628 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
629 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
630 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
631 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
632 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
633 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
634
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000635static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000636 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
637 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
638 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
639 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
640 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
641 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
642 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
643 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
644
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100645static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000646 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
647 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
648
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100649static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000650 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
651 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
652
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100653static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000654 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
655 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
656
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100657static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000658 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
659 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
660
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100661static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200662static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
663 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000664{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100665 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000666 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100667 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000668 return( 0 );
669}
670
Paul Bakker7dc4c442014-02-01 22:50:26 +0100671#define CHK( c ) if( (c) != 0 ) \
672 { \
673 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200674 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100675 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100676 }
677
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000678/*
679 * Checkup routine
680 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200681int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000682{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200683 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000684 unsigned char buf[16];
685
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200686 mbedtls_ctr_drbg_init( &ctx );
687
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000688 /*
689 * Based on a NIST CTR_DRBG test vector (PR = True)
690 */
691 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200692 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000693
694 test_offset = 0;
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200695 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
696 CHK( mbedtls_ctr_drbg_seed( &ctx,
697 ctr_drbg_self_test_entropy,
698 (void *) entropy_source_pr,
699 nonce_pers_pr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200700 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
701 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
702 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
703 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000704
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100705 mbedtls_ctr_drbg_free( &ctx );
706
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000707 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200708 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000709
710 /*
711 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
712 */
713 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200714 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000715
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100716 mbedtls_ctr_drbg_init( &ctx );
717
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000718 test_offset = 0;
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200719 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
720 CHK( mbedtls_ctr_drbg_seed( &ctx,
721 ctr_drbg_self_test_entropy,
722 (void *) entropy_source_nopr,
723 nonce_pers_nopr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200724 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
725 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
726 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100727 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000728
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100729 mbedtls_ctr_drbg_free( &ctx );
730
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000731 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200732 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000733
734 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200735 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000736
737 return( 0 );
738}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200739#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000740
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200741#endif /* MBEDTLS_CTR_DRBG_C */