blob: 32b34e462a6d2f440bd4520ba57e6b2b6ee3f29d [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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020077void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000078{
79 ctx->prediction_resistance = resistance;
80}
81
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020082void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000083{
84 ctx->entropy_len = len;
85}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +020086
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020087void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000088{
89 ctx->reseed_interval = interval;
90}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +020091
92static int block_cipher_df( unsigned char *output,
93 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000094{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020095 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
96 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
97 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
98 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +010099 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200100 mbedtls_aes_context aes_ctx;
Dvir Markovich1b364992017-06-26 13:43:34 +0300101 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000102
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200103 int i, j;
104 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000105
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200106 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
107 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100108
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200109 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
110 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000111
112 /*
113 * Construct IV (16 bytes) and S in buffer
114 * IV = Counter (in 32-bits) padded to 16 with zeroes
115 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
116 * data || 0x80
117 * (Total is padded to a multiple of 16-bytes with zeroes)
118 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200119 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000120 *p++ = ( data_len >> 24 ) & 0xff;
121 *p++ = ( data_len >> 16 ) & 0xff;
122 *p++ = ( data_len >> 8 ) & 0xff;
123 *p++ = ( data_len ) & 0xff;
124 p += 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200125 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000126 memcpy( p, data, data_len );
127 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000128
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200129 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000130
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200131 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000132 key[i] = i;
133
Dvir Markovich1b364992017-06-26 13:43:34 +0300134 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
135 {
136 goto exit;
137 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000138
139 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200140 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000141 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200142 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000143 {
144 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200145 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000146 use_len = buf_len;
147
148 while( use_len > 0 )
149 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200150 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000151 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200152 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
153 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
154 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000155
Dvir Markovich1b364992017-06-26 13:43:34 +0300156 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ) ) != 0 )
157 {
158 goto exit;
159 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000160 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200161
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200162 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000163
164 /*
165 * Update IV
166 */
167 buf[3]++;
168 }
169
170 /*
171 * Do final encryption with reduced data
172 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300173 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
174 {
175 goto exit;
176 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200177 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000178 p = output;
179
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200180 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000181 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300182 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) ) != 0 )
183 {
184 goto exit;
185 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200186 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
187 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000188 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300189exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200190 mbedtls_aes_free( &aes_ctx );
Dvir Markovich1b364992017-06-26 13:43:34 +0300191 /*
192 * tidy up the stack
193 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500194 mbedtls_platform_zeroize( buf, sizeof( buf ) );
195 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
196 mbedtls_platform_zeroize( key, sizeof( key ) );
197 mbedtls_platform_zeroize( chain, sizeof( chain ) );
Dvir Markovich1b364992017-06-26 13:43:34 +0300198 if( 0 != ret )
199 {
200 /*
201 * wipe partial seed from memory
202 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500203 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
Dvir Markovich1b364992017-06-26 13:43:34 +0300204 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200205
Dvir Markovich1b364992017-06-26 13:43:34 +0300206 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000207}
208
Gilles Peskineed7da592018-08-03 20:16:52 +0200209/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
210 * ctr_drbg_update_internal(ctx, provided_data)
211 * implements
212 * CTR_DRBG_Update(provided_data, Key, V)
213 * with inputs and outputs
214 * ctx->aes_ctx = Key
215 * ctx->counter = V
216 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200217static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
218 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000219{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200220 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000221 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000222 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300223 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000224
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200225 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000226
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200227 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000228 {
229 /*
230 * Increase counter
231 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200232 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000233 if( ++ctx->counter[i - 1] != 0 )
234 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000235
236 /*
237 * Crypt counter block
238 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300239 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200240 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000241
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200242 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000243 }
244
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200245 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000246 tmp[i] ^= data[i];
247
248 /*
249 * Update key and counter
250 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300251 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200252 goto exit;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200253 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000254
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200255exit:
256 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
257 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000258}
259
Gilles Peskineed7da592018-08-03 20:16:52 +0200260/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
261 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
262 * implements
263 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
264 * security_strength) -> initial_working_state
265 * with inputs
266 * ctx->counter = all-bits-0
267 * ctx->aes_ctx = context from all-bits-0 key
268 * additional[:add_len] = entropy_input || nonce || personalization_string
269 * and with outputs
270 * ctx = initial_working_state
271 */
Gilles Peskined9199932018-09-11 16:41:54 +0200272int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
273 const unsigned char *additional,
274 size_t add_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000275{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200276 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Gilles Peskined9199932018-09-11 16:41:54 +0200277 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000278
Gilles Peskined9199932018-09-11 16:41:54 +0200279 if( add_len == 0 )
280 return( 0 );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100281
Gilles Peskined9199932018-09-11 16:41:54 +0200282 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
283 goto exit;
284 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
285 goto exit;
286
287exit:
288 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
289 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000290}
291
Gilles Peskined9199932018-09-11 16:41:54 +0200292#if !defined(MBEDTLS_DEPRECATED_REMOVED)
293void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
294 const unsigned char *additional,
295 size_t add_len )
296{
297 /* MAX_INPUT would be more logical here, but we have to match
298 * block_cipher_df()'s limits since we can't propagate errors */
299 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
300 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
301 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
302}
303#endif /* MBEDTLS_DEPRECATED_REMOVED */
304
Gilles Peskineed7da592018-08-03 20:16:52 +0200305/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
306 * mbedtls_ctr_drbg_reseed(ctx, additional, len)
307 * implements
308 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
309 * -> new_working_state
310 * with inputs
311 * ctx contains working_state
312 * additional[:len] = additional_input
313 * and entropy_input comes from calling ctx->f_entropy
314 * and with output
315 * ctx contains new_working_state
316 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200317int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000318 const unsigned char *additional, size_t len )
319{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200320 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000321 size_t seedlen = 0;
Dvir Markovich1b364992017-06-26 13:43:34 +0300322 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000323
Andres Amaya Garcia6a543362017-01-17 23:04:22 +0000324 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
325 len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200326 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000327
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200328 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000329
330 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200331 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000332 */
333 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
334 ctx->entropy_len ) )
335 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200336 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000337 }
338
339 seedlen += ctx->entropy_len;
340
341 /*
342 * Add additional data
343 */
344 if( additional && len )
345 {
346 memcpy( seed + seedlen, additional, len );
347 seedlen += len;
348 }
349
350 /*
351 * Reduce to 384 bits
352 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300353 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200354 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000355
356 /*
357 * Update state
358 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300359 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200360 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000361 ctx->reseed_counter = 1;
362
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200363exit:
364 mbedtls_platform_zeroize( seed, sizeof( seed ) );
365 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000366}
Paul Bakker9af723c2014-05-01 13:03:14 +0200367
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200368/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
Gilles Peskine912ffe42019-10-04 12:15:55 +0200369 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200370 * implements
371 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
372 * security_strength) -> initial_working_state
373 * with inputs
374 * custom[:len] = nonce || personalization_string
Gilles Peskine912ffe42019-10-04 12:15:55 +0200375 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200376 * and with outputs
377 * ctx = initial_working_state
378 */
Gilles Peskine912ffe42019-10-04 12:15:55 +0200379int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
380 int (*f_entropy)(void *, unsigned char *, size_t),
381 void *p_entropy,
382 const unsigned char *custom,
383 size_t len )
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200384{
385 int ret;
386 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
387
388 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
389
390 mbedtls_aes_init( &ctx->aes_ctx );
391
392 ctx->f_entropy = f_entropy;
393 ctx->p_entropy = p_entropy;
394
Gilles Peskine912ffe42019-10-04 12:15:55 +0200395 if( ctx->entropy_len == 0 )
396 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200397 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
398
399 /*
400 * Initialize with an empty key
401 */
402 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
403 {
404 return( ret );
405 }
406
407 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
408 {
409 return( ret );
410 }
411 return( 0 );
412}
413
Gilles Peskine912ffe42019-10-04 12:15:55 +0200414/* Backward compatibility wrapper */
415int mbedtls_ctr_drbg_seed_entropy_len(
416 mbedtls_ctr_drbg_context *ctx,
417 int (*f_entropy)(void *, unsigned char *, size_t), void *p_entropy,
418 const unsigned char *custom, size_t len,
419 size_t entropy_len )
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200420{
Gilles Peskine912ffe42019-10-04 12:15:55 +0200421 mbedtls_ctr_drbg_set_entropy_len( ctx, entropy_len );
422 return( mbedtls_ctr_drbg_seed( ctx, f_entropy, p_entropy, custom, len ) );
Gilles Peskinec4280ac2019-10-02 20:31:54 +0200423}
424
Gilles Peskineed7da592018-08-03 20:16:52 +0200425/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
426 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
427 * implements
428 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
429 * -> working_state_after_reseed
430 * if required, then
431 * CTR_DRBG_Generate(working_state_after_reseed,
432 * requested_number_of_bits, additional_input)
433 * -> status, returned_bits, new_working_state
434 * with inputs
435 * ctx contains working_state
436 * requested_number_of_bits = 8 * output_len
437 * additional[:add_len] = additional_input
438 * and entropy_input comes from calling ctx->f_entropy
439 * and with outputs
440 * status = SUCCESS (this function does the reseed internally)
441 * returned_bits = output[:output_len]
442 * ctx contains new_working_state
443 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200444int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000445 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000446 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000447{
448 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
450 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000451 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200452 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000453 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000454 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000455
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200456 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
457 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000458
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200459 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
460 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000461
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000463
464 if( ctx->reseed_counter > ctx->reseed_interval ||
465 ctx->prediction_resistance )
466 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200467 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300468 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000469 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300470 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000471 add_len = 0;
472 }
473
474 if( add_len > 0 )
475 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300476 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200477 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300478 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200479 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000480 }
481
482 while( output_len > 0 )
483 {
484 /*
485 * Increase counter
486 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200487 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000488 if( ++ctx->counter[i - 1] != 0 )
489 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000490
491 /*
492 * Crypt counter block
493 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300494 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200495 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000496
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200497 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200498 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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200518int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000519{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100520 int ret;
521 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
522
523#if defined(MBEDTLS_THREADING_C)
524 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
525 return( ret );
526#endif
527
528 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
529
530#if defined(MBEDTLS_THREADING_C)
531 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
532 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
533#endif
534
535 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000536}
537
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200538#if defined(MBEDTLS_FS_IO)
539int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000540{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200541 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000542 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200543 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000544
545 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200546 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000547
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200548 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200549 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000550
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200551 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200552 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100553 else
554 ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000555
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100556exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500557 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200558
Paul Bakkerfc754a92011-12-05 13:23:51 +0000559 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200560 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000561}
562
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200563int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000564{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100565 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200566 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000567 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200568 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200569 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000570
571 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200572 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000573
Gilles Peskine82204662018-09-11 18:43:09 +0200574 n = fread( buf, 1, sizeof( buf ), f );
575 if( fread( &c, 1, 1, f ) != 0 )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100576 {
Gilles Peskine82204662018-09-11 18:43:09 +0200577 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
578 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100579 }
Gilles Peskine82204662018-09-11 18:43:09 +0200580 if( n == 0 || ferror( f ) )
581 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100582 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200583 goto exit;
584 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000585 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200586 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200587
Gilles Peskine82204662018-09-11 18:43:09 +0200588 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
589
590exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500591 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200592 if( f != NULL )
593 fclose( f );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100594 if( ret != 0 )
595 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200596 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000597}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200598#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000599
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200600#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000601
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000602static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000603 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
604 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
605 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
606 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
607 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
608 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
609 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
610 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
611 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
612 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
613 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
614 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
615
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000616static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000617 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
618 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
619 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
620 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
621 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
622 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
623 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
624 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
625
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100626static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000627 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
628 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
629
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100630static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000631 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
632 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
633
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100634static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000635 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
636 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
637
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100638static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000639 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
640 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
641
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100642static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200643static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
644 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000645{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100646 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000647 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100648 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000649 return( 0 );
650}
651
Paul Bakker7dc4c442014-02-01 22:50:26 +0100652#define CHK( c ) if( (c) != 0 ) \
653 { \
654 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200655 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100656 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100657 }
658
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000659/*
660 * Checkup routine
661 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200662int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000663{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200664 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000665 unsigned char buf[16];
666
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200667 mbedtls_ctr_drbg_init( &ctx );
668
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000669 /*
670 * Based on a NIST CTR_DRBG test vector (PR = True)
671 */
672 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200673 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000674
675 test_offset = 0;
Gilles Peskine912ffe42019-10-04 12:15:55 +0200676 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
677 CHK( mbedtls_ctr_drbg_seed( &ctx,
678 ctr_drbg_self_test_entropy,
679 (void *) entropy_source_pr,
680 nonce_pers_pr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200681 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
682 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
683 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
684 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000685
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100686 mbedtls_ctr_drbg_free( &ctx );
687
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000688 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200689 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000690
691 /*
692 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
693 */
694 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200695 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000696
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100697 mbedtls_ctr_drbg_init( &ctx );
698
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000699 test_offset = 0;
Gilles Peskine912ffe42019-10-04 12:15:55 +0200700 mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
701 CHK( mbedtls_ctr_drbg_seed( &ctx,
702 ctr_drbg_self_test_entropy,
703 (void *) entropy_source_nopr,
704 nonce_pers_nopr, 16 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200705 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
706 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
707 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100708 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000709
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100710 mbedtls_ctr_drbg_free( &ctx );
711
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000712 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200713 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000714
715 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200716 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000717
718 return( 0 );
719}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200720#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000721
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200722#endif /* MBEDTLS_CTR_DRBG_C */