blob: c986b7019b29ec413a12e26e304b0ebf19f8895a [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/*
385 * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow
386 * NIST tests to succeed (which require known length fixed entropy)
387 */
388/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
389 * mbedtls_ctr_drbg_seed_entropy_len(ctx, f_entropy, p_entropy,
390 * custom, len, entropy_len)
391 * implements
392 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
393 * security_strength) -> initial_working_state
394 * with inputs
395 * custom[:len] = nonce || personalization_string
396 * where entropy_input comes from f_entropy for entropy_len bytes
397 * and with outputs
398 * ctx = initial_working_state
399 */
400int mbedtls_ctr_drbg_seed_entropy_len(
401 mbedtls_ctr_drbg_context *ctx,
402 int (*f_entropy)(void *, unsigned char *, size_t),
403 void *p_entropy,
404 const unsigned char *custom,
405 size_t len,
406 size_t entropy_len )
407{
408 int ret;
409 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
410
411 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
412
413 mbedtls_aes_init( &ctx->aes_ctx );
414
415 ctx->f_entropy = f_entropy;
416 ctx->p_entropy = p_entropy;
417
418 ctx->entropy_len = entropy_len;
419 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
420
421 /*
422 * Initialize with an empty key
423 */
424 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
425 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
426 {
427 return( ret );
428 }
429
430 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
431 {
432 return( ret );
433 }
434 return( 0 );
435}
436
437int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
438 int (*f_entropy)(void *, unsigned char *, size_t),
439 void *p_entropy,
440 const unsigned char *custom,
441 size_t len )
442{
443 return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy,
444 custom, len,
445 MBEDTLS_CTR_DRBG_ENTROPY_LEN ) );
446}
447
Gilles Peskineed7da592018-08-03 20:16:52 +0200448/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
449 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
450 * implements
451 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
452 * -> working_state_after_reseed
453 * if required, then
454 * CTR_DRBG_Generate(working_state_after_reseed,
455 * requested_number_of_bits, additional_input)
456 * -> status, returned_bits, new_working_state
457 * with inputs
458 * ctx contains working_state
459 * requested_number_of_bits = 8 * output_len
460 * additional[:add_len] = additional_input
461 * and entropy_input comes from calling ctx->f_entropy
462 * and with outputs
463 * status = SUCCESS (this function does the reseed internally)
464 * returned_bits = output[:output_len]
465 * ctx contains new_working_state
466 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200467int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000468 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000469 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000470{
471 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200472 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
473 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000474 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200475 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000476 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000477 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000478
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200479 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
480 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000481
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200482 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
483 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000484
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200485 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000486
487 if( ctx->reseed_counter > ctx->reseed_interval ||
488 ctx->prediction_resistance )
489 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200490 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300491 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000492 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300493 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000494 add_len = 0;
495 }
496
497 if( add_len > 0 )
498 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300499 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200500 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300501 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200502 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000503 }
504
505 while( output_len > 0 )
506 {
507 /*
508 * Increase counter
509 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200510 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000511 if( ++ctx->counter[i - 1] != 0 )
512 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000513
514 /*
515 * Crypt counter block
516 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100517 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
518 ctx->counter, tmp ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300519 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200520 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300521 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000522
Hanno Beckera08651f2018-10-05 09:38:59 +0100523 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE )
524 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000525 /*
526 * Copy random block to destination
527 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000528 memcpy( p, tmp, use_len );
529 p += use_len;
530 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000531 }
532
Dvir Markovich1b364992017-06-26 13:43:34 +0300533 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200534 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000535
536 ctx->reseed_counter++;
537
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200538exit:
539 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
540 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000541 return( 0 );
542}
543
Hanno Beckera08651f2018-10-05 09:38:59 +0100544int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output,
545 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)
Hanno Beckera08651f2018-10-05 09:38:59 +0100566int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx,
567 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000568{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200569 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000570 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200571 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000572
573 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200574 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000575
Hanno Beckera08651f2018-10-05 09:38:59 +0100576 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf,
577 MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200578 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000579
Hanno Beckera08651f2018-10-05 09:38:59 +0100580 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) !=
581 MBEDTLS_CTR_DRBG_MAX_INPUT )
582 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200583 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Hanno Beckera08651f2018-10-05 09:38:59 +0100584 }
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100585 else
Hanno Beckera08651f2018-10-05 09:38:59 +0100586 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100587 ret = 0;
Hanno Beckera08651f2018-10-05 09:38:59 +0100588 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000589
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100590exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500591 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200592
Paul Bakkerfc754a92011-12-05 13:23:51 +0000593 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200594 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000595}
596
Hanno Beckera08651f2018-10-05 09:38:59 +0100597int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx,
598 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000599{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100600 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200601 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000602 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200603 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200604 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000605
606 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200607 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000608
Gilles Peskine82204662018-09-11 18:43:09 +0200609 n = fread( buf, 1, sizeof( buf ), f );
610 if( fread( &c, 1, 1, f ) != 0 )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100611 {
Gilles Peskine82204662018-09-11 18:43:09 +0200612 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
613 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100614 }
Gilles Peskine82204662018-09-11 18:43:09 +0200615 if( n == 0 || ferror( f ) )
616 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100617 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200618 goto exit;
619 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000620 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200621 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200622
Gilles Peskine82204662018-09-11 18:43:09 +0200623 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
624
625exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500626 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200627 if( f != NULL )
628 fclose( f );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100629 if( ret != 0 )
630 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200631 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000632}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200633#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000634
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200635#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000636
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000637static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000638 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
639 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
640 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
641 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
642 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
643 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
644 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
645 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
646 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
647 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
648 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
649 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
650
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000651static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000652 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
653 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
654 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
655 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
656 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
657 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
658 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
659 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
660
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100661static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000662 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
663 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
664
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100665static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000666 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
667 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
668
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100669static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000670 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
671 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
672
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100673static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000674 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
675 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
676
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100677static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200678static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
679 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000680{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100681 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000682 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100683 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000684 return( 0 );
685}
686
Paul Bakker7dc4c442014-02-01 22:50:26 +0100687#define CHK( c ) if( (c) != 0 ) \
688 { \
689 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200690 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100691 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100692 }
693
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000694/*
695 * Checkup routine
696 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200697int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000698{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200699 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000700 unsigned char buf[16];
701
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200702 mbedtls_ctr_drbg_init( &ctx );
703
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000704 /*
705 * Based on a NIST CTR_DRBG test vector (PR = True)
706 */
707 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200708 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000709
710 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200711 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Hanno Beckera08651f2018-10-05 09:38:59 +0100712 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
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;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200732 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Hanno Beckera08651f2018-10-05 09:38:59 +0100733 (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200734 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
735 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
736 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100737 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000738
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100739 mbedtls_ctr_drbg_free( &ctx );
740
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000741 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200742 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000743
744 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200745 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000746
747 return( 0 );
748}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200749#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000750
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200751#endif /* MBEDTLS_CTR_DRBG_C */