blob: 0045b77c6089eaf10ae0fa257fb248a84f717a0a [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)
Gilles Peskine379561f2019-10-18 16:57:48 +0200385 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
Gilles Peskine8bf56132019-10-02 20:31:54 +0200386 * implements
387 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
388 * security_strength) -> initial_working_state
389 * with inputs
390 * custom[:len] = nonce || personalization_string
Gilles Peskine379561f2019-10-18 16:57:48 +0200391 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
Gilles Peskine8bf56132019-10-02 20:31:54 +0200392 * and with outputs
393 * ctx = initial_working_state
394 */
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200395int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
396 int (*f_entropy)(void *, unsigned char *, size_t),
397 void *p_entropy,
398 const unsigned char *custom,
399 size_t len )
Gilles Peskine8bf56132019-10-02 20:31:54 +0200400{
401 int ret;
402 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
403
404 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
405
406 mbedtls_aes_init( &ctx->aes_ctx );
407
408 ctx->f_entropy = f_entropy;
409 ctx->p_entropy = p_entropy;
410
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200411 if( ctx->entropy_len == 0 )
412 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskine8bf56132019-10-02 20:31:54 +0200413 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
414
415 /*
416 * Initialize with an empty key
417 */
418 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
419 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
420 {
421 return( ret );
422 }
423
424 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
425 {
426 return( ret );
427 }
428 return( 0 );
429}
430
Gilles Peskineed7da592018-08-03 20:16:52 +0200431/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
432 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
433 * implements
434 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
435 * -> working_state_after_reseed
436 * if required, then
437 * CTR_DRBG_Generate(working_state_after_reseed,
438 * requested_number_of_bits, additional_input)
439 * -> status, returned_bits, new_working_state
440 * with inputs
441 * ctx contains working_state
442 * requested_number_of_bits = 8 * output_len
443 * additional[:add_len] = additional_input
444 * and entropy_input comes from calling ctx->f_entropy
445 * and with outputs
446 * status = SUCCESS (this function does the reseed internally)
447 * returned_bits = output[:output_len]
448 * ctx contains new_working_state
449 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200450int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000451 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000452 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000453{
454 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200455 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
456 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000457 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200458 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000459 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000460 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000461
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
463 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000464
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200465 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
466 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000467
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200468 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000469
470 if( ctx->reseed_counter > ctx->reseed_interval ||
471 ctx->prediction_resistance )
472 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200473 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300474 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000475 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300476 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000477 add_len = 0;
478 }
479
480 if( add_len > 0 )
481 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300482 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200483 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300484 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200485 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000486 }
487
488 while( output_len > 0 )
489 {
490 /*
491 * Increase counter
492 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200493 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000494 if( ++ctx->counter[i - 1] != 0 )
495 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000496
497 /*
498 * Crypt counter block
499 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100500 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
501 ctx->counter, tmp ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300502 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200503 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300504 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000505
Hanno Beckera08651f2018-10-05 09:38:59 +0100506 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE )
507 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000508 /*
509 * Copy random block to destination
510 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000511 memcpy( p, tmp, use_len );
512 p += use_len;
513 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000514 }
515
Dvir Markovich1b364992017-06-26 13:43:34 +0300516 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200517 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000518
519 ctx->reseed_counter++;
520
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200521exit:
522 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
523 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000524 return( 0 );
525}
526
Hanno Beckera08651f2018-10-05 09:38:59 +0100527int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output,
528 size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000529{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100530 int ret;
531 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
532
533#if defined(MBEDTLS_THREADING_C)
534 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
535 return( ret );
536#endif
537
538 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
539
540#if defined(MBEDTLS_THREADING_C)
541 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
542 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
543#endif
544
545 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000546}
547
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200548#if defined(MBEDTLS_FS_IO)
Hanno Beckera08651f2018-10-05 09:38:59 +0100549int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx,
550 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000551{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200552 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000553 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200554 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000555
556 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200557 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000558
Hanno Beckera08651f2018-10-05 09:38:59 +0100559 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf,
560 MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200561 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000562
Hanno Beckera08651f2018-10-05 09:38:59 +0100563 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) !=
564 MBEDTLS_CTR_DRBG_MAX_INPUT )
565 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200566 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Hanno Beckera08651f2018-10-05 09:38:59 +0100567 }
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100568 else
Hanno Beckera08651f2018-10-05 09:38:59 +0100569 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100570 ret = 0;
Hanno Beckera08651f2018-10-05 09:38:59 +0100571 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000572
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100573exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500574 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200575
Paul Bakkerfc754a92011-12-05 13:23:51 +0000576 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200577 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000578}
579
Hanno Beckera08651f2018-10-05 09:38:59 +0100580int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx,
581 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000582{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100583 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200584 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000585 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200586 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200587 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000588
589 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200590 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000591
Gilles Peskine82204662018-09-11 18:43:09 +0200592 n = fread( buf, 1, sizeof( buf ), f );
593 if( fread( &c, 1, 1, f ) != 0 )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100594 {
Gilles Peskine82204662018-09-11 18:43:09 +0200595 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
596 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100597 }
Gilles Peskine82204662018-09-11 18:43:09 +0200598 if( n == 0 || ferror( f ) )
599 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100600 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200601 goto exit;
602 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000603 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200604 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200605
Gilles Peskine82204662018-09-11 18:43:09 +0200606 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
607
608exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500609 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200610 if( f != NULL )
611 fclose( f );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100612 if( ret != 0 )
613 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200614 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000615}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200616#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000617
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200618#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000619
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000620static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000621 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
622 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
623 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
624 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
625 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
626 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
627 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
628 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
629 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
630 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
631 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
632 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
633
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000634static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000635 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
636 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
637 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
638 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
639 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
640 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
641 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
642 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
643
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100644static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000645 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
646 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
647
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100648static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000649 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
650 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
651
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100652static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000653 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
654 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
655
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100656static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000657 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
658 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
659
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100660static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200661static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
662 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000663{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100664 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000665 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100666 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000667 return( 0 );
668}
669
Paul Bakker7dc4c442014-02-01 22:50:26 +0100670#define CHK( c ) if( (c) != 0 ) \
671 { \
672 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200673 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100674 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100675 }
676
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000677/*
678 * Checkup routine
679 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200680int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000681{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200682 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000683 unsigned char buf[16];
684
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200685 mbedtls_ctr_drbg_init( &ctx );
686
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000687 /*
688 * Based on a NIST CTR_DRBG test vector (PR = True)
689 */
690 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200691 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000692
693 test_offset = 0;
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200694 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
695 CHK( mbedtls_ctr_drbg_seed( &ctx,
696 ctr_drbg_self_test_entropy,
697 (void *) entropy_source_pr,
698 nonce_pers_pr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200699 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
700 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
701 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
702 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000703
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100704 mbedtls_ctr_drbg_free( &ctx );
705
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000706 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200707 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000708
709 /*
710 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
711 */
712 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200713 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000714
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100715 mbedtls_ctr_drbg_init( &ctx );
716
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000717 test_offset = 0;
Gilles Peskine50ed86b2019-10-04 12:15:55 +0200718 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
719 CHK( mbedtls_ctr_drbg_seed( &ctx,
720 ctr_drbg_self_test_entropy,
721 (void *) entropy_source_nopr,
722 nonce_pers_nopr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200723 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
724 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
725 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100726 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000727
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100728 mbedtls_ctr_drbg_free( &ctx );
729
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000730 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200731 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000732
733 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200734 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000735
736 return( 0 );
737}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200738#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000739
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200740#endif /* MBEDTLS_CTR_DRBG_C */