blob: 9222f4ef711069d8109a50744881ded9f7591ca9 [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{
Manuel Pégourié-Gonnard7a346b82019-10-02 14:47:01 +020058 mbedtls_platform_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é-Gonnard7a346b82019-10-02 14:47:01 +0200109 mbedtls_platform_memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200110 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;
Teppo Järvelin91d79382019-10-02 09:09:31 +0300126 mbedtls_platform_memcpy( p, data, data_len );
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000127 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é-Gonnard7a346b82019-10-02 14:47:01 +0200145 mbedtls_platform_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
Teppo Järvelin91d79382019-10-02 09:09:31 +0300162 mbedtls_platform_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 }
Teppo Järvelin91d79382019-10-02 09:09:31 +0300186 mbedtls_platform_memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200187 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é-Gonnard7a346b82019-10-02 14:47:01 +0200225 mbedtls_platform_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;
Teppo Järvelin91d79382019-10-02 09:09:31 +0300253 mbedtls_platform_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é-Gonnard7a346b82019-10-02 14:47:01 +0200328 mbedtls_platform_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 {
Teppo Järvelin91d79382019-10-02 09:09:31 +0300346 mbedtls_platform_memcpy( seed + seedlen, additional, len );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000347 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 Peskinef0bf7572019-10-02 20:31:54 +0200368/*
369 * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow
370 * NIST tests to succeed (which require known length fixed entropy)
371 */
372/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
373 * mbedtls_ctr_drbg_seed_entropy_len(ctx, f_entropy, p_entropy,
374 * custom, len, entropy_len)
375 * implements
376 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
377 * security_strength) -> initial_working_state
378 * with inputs
379 * custom[:len] = nonce || personalization_string
380 * where entropy_input comes from f_entropy for entropy_len bytes
381 * and with outputs
382 * ctx = initial_working_state
383 */
384int mbedtls_ctr_drbg_seed_entropy_len(
385 mbedtls_ctr_drbg_context *ctx,
386 int (*f_entropy)(void *, unsigned char *, size_t),
387 void *p_entropy,
388 const unsigned char *custom,
389 size_t len,
390 size_t entropy_len )
391{
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
402 ctx->entropy_len = entropy_len;
403 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
404
405 /*
406 * Initialize with an empty key
407 */
408 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
409 {
410 return( ret );
411 }
412
413 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
414 {
415 return( ret );
416 }
417 return( 0 );
418}
419
420int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
421 int (*f_entropy)(void *, unsigned char *, size_t),
422 void *p_entropy,
423 const unsigned char *custom,
424 size_t len )
425{
426 return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy, custom, len,
427 MBEDTLS_CTR_DRBG_ENTROPY_LEN ) );
428}
429
Gilles Peskineed7da592018-08-03 20:16:52 +0200430/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
431 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
432 * implements
433 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
434 * -> working_state_after_reseed
435 * if required, then
436 * CTR_DRBG_Generate(working_state_after_reseed,
437 * requested_number_of_bits, additional_input)
438 * -> status, returned_bits, new_working_state
439 * with inputs
440 * ctx contains working_state
441 * requested_number_of_bits = 8 * output_len
442 * additional[:add_len] = additional_input
443 * and entropy_input comes from calling ctx->f_entropy
444 * and with outputs
445 * status = SUCCESS (this function does the reseed internally)
446 * returned_bits = output[:output_len]
447 * ctx contains new_working_state
448 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000450 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000451 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000452{
453 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200454 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
455 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000456 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200457 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000458 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000459 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000460
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200461 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
462 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000463
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200464 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
465 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000466
Manuel Pégourié-Gonnard7a346b82019-10-02 14:47:01 +0200467 mbedtls_platform_memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000468
469 if( ctx->reseed_counter > ctx->reseed_interval ||
470 ctx->prediction_resistance )
471 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200472 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300473 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000474 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300475 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000476 add_len = 0;
477 }
478
479 if( add_len > 0 )
480 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300481 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200482 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300483 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200484 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000485 }
486
487 while( output_len > 0 )
488 {
489 /*
490 * Increase counter
491 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200492 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000493 if( ++ctx->counter[i - 1] != 0 )
494 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000495
496 /*
497 * Crypt counter block
498 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300499 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200500 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000501
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200502 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200503 output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000504 /*
505 * Copy random block to destination
506 */
Teppo Järvelin91d79382019-10-02 09:09:31 +0300507 mbedtls_platform_memcpy( p, tmp, use_len );
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000508 p += use_len;
509 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000510 }
511
Dvir Markovich1b364992017-06-26 13:43:34 +0300512 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200513 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000514
515 ctx->reseed_counter++;
516
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200517exit:
518 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
519 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000520 return( 0 );
521}
522
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200523int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000524{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100525 int ret;
526 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
527
528#if defined(MBEDTLS_THREADING_C)
529 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
530 return( ret );
531#endif
532
533 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
534
535#if defined(MBEDTLS_THREADING_C)
536 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
537 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
538#endif
539
540 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000541}
542
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200543#if defined(MBEDTLS_FS_IO)
544int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000545{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200546 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000547 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200548 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000549
550 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200551 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000552
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200553 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200554 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000555
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200556 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200557 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100558 else
559 ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000560
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100561exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500562 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200563
Paul Bakkerfc754a92011-12-05 13:23:51 +0000564 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200565 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000566}
567
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200568int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000569{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100570 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200571 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000572 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200573 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200574 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000575
576 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200577 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000578
Gilles Peskine82204662018-09-11 18:43:09 +0200579 n = fread( buf, 1, sizeof( buf ), f );
580 if( fread( &c, 1, 1, f ) != 0 )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100581 {
Gilles Peskine82204662018-09-11 18:43:09 +0200582 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
583 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100584 }
Gilles Peskine82204662018-09-11 18:43:09 +0200585 if( n == 0 || ferror( f ) )
586 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100587 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200588 goto exit;
589 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000590 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200591 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200592
Gilles Peskine82204662018-09-11 18:43:09 +0200593 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
594
595exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500596 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200597 if( f != NULL )
598 fclose( f );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100599 if( ret != 0 )
600 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200601 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000602}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200603#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000604
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200605#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000606
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000607static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000608 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
609 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
610 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
611 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
612 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
613 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
614 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
615 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
616 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
617 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
618 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
619 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
620
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000621static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000622 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
623 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
624 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
625 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
626 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
627 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
628 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
629 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
630
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100631static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000632 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
633 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
634
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100635static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000636 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
637 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
638
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100639static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000640 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
641 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
642
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100643static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000644 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
645 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
646
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100647static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200648static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
649 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000650{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100651 const unsigned char *p = data;
Teppo Järvelinb5c46712019-10-04 13:35:55 +0300652 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100653 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000654 return( 0 );
655}
656
Paul Bakker7dc4c442014-02-01 22:50:26 +0100657#define CHK( c ) if( (c) != 0 ) \
658 { \
659 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200660 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100661 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100662 }
663
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000664/*
665 * Checkup routine
666 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200667int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000668{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200669 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000670 unsigned char buf[16];
671
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200672 mbedtls_ctr_drbg_init( &ctx );
673
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000674 /*
675 * Based on a NIST CTR_DRBG test vector (PR = True)
676 */
677 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200678 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000679
680 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200681 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000682 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200683 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
684 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
685 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
686 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000687
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100688 mbedtls_ctr_drbg_free( &ctx );
689
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000690 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200691 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000692
693 /*
694 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
695 */
696 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200697 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000698
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100699 mbedtls_ctr_drbg_init( &ctx );
700
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000701 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200702 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000703 (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200704 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
705 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
706 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100707 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000708
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100709 mbedtls_ctr_drbg_free( &ctx );
710
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000711 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200712 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000713
714 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200715 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000716
717 return( 0 );
718}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200719#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000720
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200721#endif /* MBEDTLS_CTR_DRBG_C */