blob: 92316dabbdac210d2ef272690abd8e0b8b7dffa9 [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
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200340 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
341 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
342 if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200343 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000344
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200345 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000346
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200347 /* Gather entropy_len bytes of entropy to seed state. */
348 if( 0 != ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000349 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200350 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000351 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000352 seedlen += ctx->entropy_len;
353
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200354 /* Add additional data if provided. */
355 if( additional != NULL && len != 0 )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000356 {
357 memcpy( seed + seedlen, additional, len );
358 seedlen += len;
359 }
360
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200361 /* Reduce to 384 bits. */
Dvir Markovich1b364992017-06-26 13:43:34 +0300362 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200363 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000364
Gilles Peskinedbd3f7c2019-10-22 17:25:30 +0200365 /* Update state. */
Dvir Markovich1b364992017-06-26 13:43:34 +0300366 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200367 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000368 ctx->reseed_counter = 1;
369
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200370exit:
371 mbedtls_platform_zeroize( seed, sizeof( seed ) );
372 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000373}
Paul Bakker9af723c2014-05-01 13:03:14 +0200374
Gilles Peskine8bf56132019-10-02 20:31:54 +0200375/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
Gilles Peskine379561f2019-10-18 16:57:48 +0200376 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
Gilles Peskine8bf56132019-10-02 20:31:54 +0200377 * implements
378 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
379 * security_strength) -> initial_working_state
380 * with inputs
381 * custom[:len] = nonce || personalization_string
Gilles Peskine379561f2019-10-18 16:57:48 +0200382 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
Gilles Peskine8bf56132019-10-02 20:31:54 +0200383 * and with outputs
384 * ctx = initial_working_state
385 */
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200386int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
387 int (*f_entropy)(void *, unsigned char *, size_t),
388 void *p_entropy,
389 const unsigned char *custom,
390 size_t len )
Gilles Peskine8bf56132019-10-02 20:31:54 +0200391{
392 int ret;
393 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
394
395 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
396
397 mbedtls_aes_init( &ctx->aes_ctx );
398
399 ctx->f_entropy = f_entropy;
400 ctx->p_entropy = p_entropy;
401
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200402 if( ctx->entropy_len == 0 )
403 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200404 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
405
406 /*
407 * Initialize with an empty key
408 */
409 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
410 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
411 {
412 return( ret );
413 }
414
415 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
416 {
417 return( ret );
418 }
419 return( 0 );
420}
421
Gilles Peskineed7da592018-08-03 20:16:52 +0200422/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
423 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
424 * implements
425 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
426 * -> working_state_after_reseed
427 * if required, then
428 * CTR_DRBG_Generate(working_state_after_reseed,
429 * requested_number_of_bits, additional_input)
430 * -> status, returned_bits, new_working_state
431 * with inputs
432 * ctx contains working_state
433 * requested_number_of_bits = 8 * output_len
434 * additional[:add_len] = additional_input
435 * and entropy_input comes from calling ctx->f_entropy
436 * and with outputs
437 * status = SUCCESS (this function does the reseed internally)
438 * returned_bits = output[:output_len]
439 * ctx contains new_working_state
440 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200441int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000442 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000443 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000444{
445 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200446 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
447 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000448 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000450 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000451 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000452
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200453 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
454 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000455
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200456 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
457 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000458
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200459 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000460
461 if( ctx->reseed_counter > ctx->reseed_interval ||
462 ctx->prediction_resistance )
463 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200464 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300465 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000466 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300467 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000468 add_len = 0;
469 }
470
471 if( add_len > 0 )
472 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300473 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200474 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300475 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200476 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000477 }
478
479 while( output_len > 0 )
480 {
481 /*
482 * Increase counter
483 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200484 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000485 if( ++ctx->counter[i - 1] != 0 )
486 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000487
488 /*
489 * Crypt counter block
490 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100491 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
492 ctx->counter, tmp ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300493 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200494 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300495 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000496
Hanno Beckera08651f2018-10-05 09:38:59 +0100497 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE )
498 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000499 /*
500 * Copy random block to destination
501 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000502 memcpy( p, tmp, use_len );
503 p += use_len;
504 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000505 }
506
Dvir Markovich1b364992017-06-26 13:43:34 +0300507 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200508 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000509
510 ctx->reseed_counter++;
511
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200512exit:
513 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
514 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000515 return( 0 );
516}
517
Hanno Beckera08651f2018-10-05 09:38:59 +0100518int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output,
519 size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000520{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100521 int ret;
522 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
523
524#if defined(MBEDTLS_THREADING_C)
525 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
526 return( ret );
527#endif
528
529 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
530
531#if defined(MBEDTLS_THREADING_C)
532 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
533 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
534#endif
535
536 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000537}
538
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200539#if defined(MBEDTLS_FS_IO)
Hanno Beckera08651f2018-10-05 09:38:59 +0100540int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx,
541 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000542{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200543 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000544 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200545 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000546
547 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200548 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000549
Hanno Beckera08651f2018-10-05 09:38:59 +0100550 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf,
551 MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200552 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000553
Hanno Beckera08651f2018-10-05 09:38:59 +0100554 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) !=
555 MBEDTLS_CTR_DRBG_MAX_INPUT )
556 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200557 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Hanno Beckera08651f2018-10-05 09:38:59 +0100558 }
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100559 else
Hanno Beckera08651f2018-10-05 09:38:59 +0100560 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100561 ret = 0;
Hanno Beckera08651f2018-10-05 09:38:59 +0100562 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000563
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100564exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500565 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200566
Paul Bakkerfc754a92011-12-05 13:23:51 +0000567 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200568 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000569}
570
Hanno Beckera08651f2018-10-05 09:38:59 +0100571int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx,
572 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000573{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100574 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200575 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000576 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200577 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200578 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000579
580 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200581 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000582
Gilles Peskine82204662018-09-11 18:43:09 +0200583 n = fread( buf, 1, sizeof( buf ), f );
584 if( fread( &c, 1, 1, f ) != 0 )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100585 {
Gilles Peskine82204662018-09-11 18:43:09 +0200586 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
587 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100588 }
Gilles Peskine82204662018-09-11 18:43:09 +0200589 if( n == 0 || ferror( f ) )
590 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100591 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200592 goto exit;
593 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000594 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200595 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200596
Gilles Peskine82204662018-09-11 18:43:09 +0200597 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
598
599exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500600 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200601 if( f != NULL )
602 fclose( f );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100603 if( ret != 0 )
604 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200605 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000606}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200607#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000608
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200609#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000610
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000611static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000612 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
613 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
614 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
615 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
616 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
617 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
618 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
619 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
620 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
621 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
622 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
623 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
624
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000625static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000626 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
627 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
628 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
629 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
630 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
631 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
632 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
633 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
634
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100635static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000636 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
637 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
638
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100639static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000640 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
641 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
642
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100643static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000644 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
645 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
646
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100647static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000648 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
649 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
650
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100651static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200652static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
653 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000654{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100655 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000656 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100657 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000658 return( 0 );
659}
660
Paul Bakker7dc4c442014-02-01 22:50:26 +0100661#define CHK( c ) if( (c) != 0 ) \
662 { \
663 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200664 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100665 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100666 }
667
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000668/*
669 * Checkup routine
670 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200671int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000672{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200673 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000674 unsigned char buf[16];
675
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200676 mbedtls_ctr_drbg_init( &ctx );
677
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000678 /*
679 * Based on a NIST CTR_DRBG test vector (PR = True)
680 */
681 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200682 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000683
684 test_offset = 0;
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200685 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
686 CHK( mbedtls_ctr_drbg_seed( &ctx,
687 ctr_drbg_self_test_entropy,
688 (void *) entropy_source_pr,
689 nonce_pers_pr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200690 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
691 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
692 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
693 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000694
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100695 mbedtls_ctr_drbg_free( &ctx );
696
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000697 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200698 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000699
700 /*
701 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
702 */
703 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200704 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000705
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100706 mbedtls_ctr_drbg_init( &ctx );
707
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000708 test_offset = 0;
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200709 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
710 CHK( mbedtls_ctr_drbg_seed( &ctx,
711 ctr_drbg_self_test_entropy,
712 (void *) entropy_source_nopr,
713 nonce_pers_nopr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200714 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
715 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
716 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100717 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000718
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100719 mbedtls_ctr_drbg_free( &ctx );
720
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000721 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200722 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000723
724 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200725 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000726
727 return( 0 );
728}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200729#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000730
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200731#endif /* MBEDTLS_CTR_DRBG_C */