blob: 0db7beb29df88f06f042967c6c8e3f2e407ae8c1 [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
65/*
Simon Butcher71c7ac52016-05-10 23:47:30 +010066 * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow
67 * NIST tests to succeed (which require known length fixed entropy)
Paul Bakker18d32912011-12-10 21:42:49 +000068 */
Gilles Peskineed7da592018-08-03 20:16:52 +020069/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
70 * mbedtls_ctr_drbg_seed_entropy_len(ctx, f_entropy, p_entropy,
71 * custom, len, entropy_len)
72 * implements
73 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
74 * security_strength) -> initial_working_state
75 * with inputs
76 * custom[:len] = nonce || personalization_string
77 * where entropy_input comes from f_entropy for entropy_len bytes
78 * and with outputs
79 * ctx = initial_working_state
80 */
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020081int mbedtls_ctr_drbg_seed_entropy_len(
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020082 mbedtls_ctr_drbg_context *ctx,
Paul Bakker0e04d0e2011-11-27 14:46:59 +000083 int (*f_entropy)(void *, unsigned char *, size_t),
84 void *p_entropy,
Paul Bakker1bc9efc2011-12-03 11:29:32 +000085 const unsigned char *custom,
Paul Bakker18d32912011-12-10 21:42:49 +000086 size_t len,
87 size_t entropy_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000088{
89 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020090 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Paul Bakker0e04d0e2011-11-27 14:46:59 +000091
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020092 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000093
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020094 mbedtls_aes_init( &ctx->aes_ctx );
Paul Bakkerc7ea99a2014-06-18 11:12:03 +020095
Paul Bakker0e04d0e2011-11-27 14:46:59 +000096 ctx->f_entropy = f_entropy;
97 ctx->p_entropy = p_entropy;
98
Paul Bakker18d32912011-12-10 21:42:49 +000099 ctx->entropy_len = entropy_len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200100 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000101
102 /*
103 * Initialize with an empty key
104 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100105 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
106 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300107 {
108 return( ret );
109 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000110
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200111 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300112 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000113 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300114 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000115 return( 0 );
116}
117
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200118int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker18d32912011-12-10 21:42:49 +0000119 int (*f_entropy)(void *, unsigned char *, size_t),
120 void *p_entropy,
121 const unsigned char *custom,
122 size_t len )
123{
Hanno Beckera08651f2018-10-05 09:38:59 +0100124 return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy,
125 custom, len,
126 MBEDTLS_CTR_DRBG_ENTROPY_LEN ) );
Paul Bakker18d32912011-12-10 21:42:49 +0000127}
128
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200129void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
Paul Bakkerfff03662014-06-18 16:21:25 +0200130{
131 if( ctx == NULL )
132 return;
133
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100134#if defined(MBEDTLS_THREADING_C)
135 mbedtls_mutex_free( &ctx->mutex );
136#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200137 mbedtls_aes_free( &ctx->aes_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500138 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Paul Bakkerfff03662014-06-18 16:21:25 +0200139}
140
Hanno Beckera08651f2018-10-05 09:38:59 +0100141void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx,
142 int resistance )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000143{
144 ctx->prediction_resistance = resistance;
145}
146
Hanno Beckera08651f2018-10-05 09:38:59 +0100147void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx,
148 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000149{
150 ctx->entropy_len = len;
151}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200152
Hanno Beckera08651f2018-10-05 09:38:59 +0100153void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx,
154 int interval )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000155{
156 ctx->reseed_interval = interval;
157}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200158
159static int block_cipher_df( unsigned char *output,
160 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000161{
Hanno Beckera08651f2018-10-05 09:38:59 +0100162 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
163 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200164 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
165 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
166 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100167 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200168 mbedtls_aes_context aes_ctx;
Dvir Markovich1b364992017-06-26 13:43:34 +0300169 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000170
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200171 int i, j;
172 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000173
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200174 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
175 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100176
Hanno Beckera08651f2018-10-05 09:38:59 +0100177 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
178 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200179 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000180
181 /*
182 * Construct IV (16 bytes) and S in buffer
183 * IV = Counter (in 32-bits) padded to 16 with zeroes
184 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
185 * data || 0x80
186 * (Total is padded to a multiple of 16-bytes with zeroes)
187 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200188 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000189 *p++ = ( data_len >> 24 ) & 0xff;
190 *p++ = ( data_len >> 16 ) & 0xff;
191 *p++ = ( data_len >> 8 ) & 0xff;
192 *p++ = ( data_len ) & 0xff;
193 p += 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200194 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000195 memcpy( p, data, data_len );
196 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000197
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200198 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000199
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200200 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000201 key[i] = i;
202
Hanno Beckera08651f2018-10-05 09:38:59 +0100203 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key,
204 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300205 {
206 goto exit;
207 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000208
209 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200210 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000211 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200212 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000213 {
214 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200215 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000216 use_len = buf_len;
217
218 while( use_len > 0 )
219 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200220 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000221 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200222 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
223 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
224 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000225
Hanno Beckera08651f2018-10-05 09:38:59 +0100226 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
227 chain, chain ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300228 {
229 goto exit;
230 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000231 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200232
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200233 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000234
235 /*
236 * Update IV
237 */
238 buf[3]++;
239 }
240
241 /*
242 * Do final encryption with reduced data
243 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100244 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp,
245 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300246 {
247 goto exit;
248 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200249 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000250 p = output;
251
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200252 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000253 {
Hanno Beckera08651f2018-10-05 09:38:59 +0100254 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
255 iv, iv ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300256 {
257 goto exit;
258 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200259 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
260 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000261 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300262exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200263 mbedtls_aes_free( &aes_ctx );
Dvir Markovich1b364992017-06-26 13:43:34 +0300264 /*
265 * tidy up the stack
266 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500267 mbedtls_platform_zeroize( buf, sizeof( buf ) );
268 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
269 mbedtls_platform_zeroize( key, sizeof( key ) );
270 mbedtls_platform_zeroize( chain, sizeof( chain ) );
Dvir Markovich1b364992017-06-26 13:43:34 +0300271 if( 0 != ret )
272 {
273 /*
274 * wipe partial seed from memory
275 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500276 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
Dvir Markovich1b364992017-06-26 13:43:34 +0300277 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200278
Dvir Markovich1b364992017-06-26 13:43:34 +0300279 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000280}
281
Gilles Peskineed7da592018-08-03 20:16:52 +0200282/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
283 * ctr_drbg_update_internal(ctx, provided_data)
284 * implements
285 * CTR_DRBG_Update(provided_data, Key, V)
286 * with inputs and outputs
287 * ctx->aes_ctx = Key
288 * ctx->counter = V
289 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200290static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
Hanno Beckera08651f2018-10-05 09:38:59 +0100291 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000292{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200293 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000294 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000295 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300296 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000297
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200298 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000299
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200300 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000301 {
302 /*
303 * Increase counter
304 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200305 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000306 if( ++ctx->counter[i - 1] != 0 )
307 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000308
309 /*
310 * Crypt counter block
311 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100312 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
313 ctx->counter, p ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300314 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200315 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300316 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000317
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200318 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000319 }
320
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200321 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000322 tmp[i] ^= data[i];
323
324 /*
325 * Update key and counter
326 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100327 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp,
328 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300329 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200330 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300331 }
Hanno Beckera08651f2018-10-05 09:38:59 +0100332 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
333 MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000334
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200335exit:
336 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
337 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000338}
339
Gilles Peskineed7da592018-08-03 20:16:52 +0200340/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
341 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
342 * implements
343 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
344 * security_strength) -> initial_working_state
345 * with inputs
346 * ctx->counter = all-bits-0
347 * ctx->aes_ctx = context from all-bits-0 key
348 * additional[:add_len] = entropy_input || nonce || personalization_string
349 * and with outputs
350 * ctx = initial_working_state
351 */
Gilles Peskined9199932018-09-11 16:41:54 +0200352int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
353 const unsigned char *additional,
354 size_t add_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000355{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200356 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Gilles Peskined9199932018-09-11 16:41:54 +0200357 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000358
Gilles Peskined9199932018-09-11 16:41:54 +0200359 if( add_len == 0 )
360 return( 0 );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100361
Gilles Peskined9199932018-09-11 16:41:54 +0200362 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
363 goto exit;
364 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
365 goto exit;
366
367exit:
368 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
369 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000370}
371
Gilles Peskined9199932018-09-11 16:41:54 +0200372#if !defined(MBEDTLS_DEPRECATED_REMOVED)
373void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
374 const unsigned char *additional,
375 size_t add_len )
376{
377 /* MAX_INPUT would be more logical here, but we have to match
378 * block_cipher_df()'s limits since we can't propagate errors */
379 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
380 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
381 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
382}
383#endif /* MBEDTLS_DEPRECATED_REMOVED */
384
Gilles Peskineed7da592018-08-03 20:16:52 +0200385/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
386 * mbedtls_ctr_drbg_reseed(ctx, additional, len)
387 * implements
388 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
389 * -> new_working_state
390 * with inputs
391 * ctx contains working_state
392 * additional[:len] = additional_input
393 * and entropy_input comes from calling ctx->f_entropy
394 * and with output
395 * ctx contains new_working_state
396 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200397int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000398 const unsigned char *additional, size_t len )
399{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200400 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000401 size_t seedlen = 0;
Dvir Markovich1b364992017-06-26 13:43:34 +0300402 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000403
Andres Amaya Garcia6a543362017-01-17 23:04:22 +0000404 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
405 len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200406 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000407
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200408 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000409
410 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200411 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000412 */
413 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
414 ctx->entropy_len ) )
415 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200416 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000417 }
418
419 seedlen += ctx->entropy_len;
420
421 /*
422 * Add additional data
423 */
424 if( additional && len )
425 {
426 memcpy( seed + seedlen, additional, len );
427 seedlen += len;
428 }
429
430 /*
431 * Reduce to 384 bits
432 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300433 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200434 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000435
436 /*
437 * Update state
438 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300439 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200440 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000441 ctx->reseed_counter = 1;
442
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200443exit:
444 mbedtls_platform_zeroize( seed, sizeof( seed ) );
445 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000446}
Paul Bakker9af723c2014-05-01 13:03:14 +0200447
Gilles Peskineed7da592018-08-03 20:16:52 +0200448/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
449 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
450 * implements
451 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
452 * -> working_state_after_reseed
453 * if required, then
454 * CTR_DRBG_Generate(working_state_after_reseed,
455 * requested_number_of_bits, additional_input)
456 * -> status, returned_bits, new_working_state
457 * with inputs
458 * ctx contains working_state
459 * requested_number_of_bits = 8 * output_len
460 * additional[:add_len] = additional_input
461 * and entropy_input comes from calling ctx->f_entropy
462 * and with outputs
463 * status = SUCCESS (this function does the reseed internally)
464 * returned_bits = output[:output_len]
465 * ctx contains new_working_state
466 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200467int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000468 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000469 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000470{
471 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200472 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
473 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000474 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200475 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000476 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000477 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000478
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200479 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
480 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000481
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200482 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
483 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000484
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200485 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000486
487 if( ctx->reseed_counter > ctx->reseed_interval ||
488 ctx->prediction_resistance )
489 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200490 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300491 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000492 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300493 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000494 add_len = 0;
495 }
496
497 if( add_len > 0 )
498 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300499 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200500 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300501 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200502 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000503 }
504
505 while( output_len > 0 )
506 {
507 /*
508 * Increase counter
509 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200510 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000511 if( ++ctx->counter[i - 1] != 0 )
512 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000513
514 /*
515 * Crypt counter block
516 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100517 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
518 ctx->counter, tmp ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300519 {
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200520 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300521 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000522
Hanno Beckera08651f2018-10-05 09:38:59 +0100523 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE )
524 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000525 /*
526 * Copy random block to destination
527 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000528 memcpy( p, tmp, use_len );
529 p += use_len;
530 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000531 }
532
Dvir Markovich1b364992017-06-26 13:43:34 +0300533 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200534 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000535
536 ctx->reseed_counter++;
537
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200538exit:
539 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
540 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000541 return( 0 );
542}
543
Hanno Beckera08651f2018-10-05 09:38:59 +0100544int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output,
545 size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000546{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100547 int ret;
548 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
549
550#if defined(MBEDTLS_THREADING_C)
551 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
552 return( ret );
553#endif
554
555 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
556
557#if defined(MBEDTLS_THREADING_C)
558 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
559 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
560#endif
561
562 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000563}
564
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200565#if defined(MBEDTLS_FS_IO)
Hanno Beckera08651f2018-10-05 09:38:59 +0100566int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx,
567 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000568{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200569 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000570 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200571 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000572
573 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200574 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000575
Hanno Beckera08651f2018-10-05 09:38:59 +0100576 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf,
577 MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200578 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000579
Hanno Beckera08651f2018-10-05 09:38:59 +0100580 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) !=
581 MBEDTLS_CTR_DRBG_MAX_INPUT )
582 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200583 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Hanno Beckera08651f2018-10-05 09:38:59 +0100584 }
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100585 else
Hanno Beckera08651f2018-10-05 09:38:59 +0100586 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100587 ret = 0;
Hanno Beckera08651f2018-10-05 09:38:59 +0100588 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000589
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100590exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500591 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200592
Paul Bakkerfc754a92011-12-05 13:23:51 +0000593 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200594 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000595}
596
Hanno Beckera08651f2018-10-05 09:38:59 +0100597int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx,
598 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000599{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100600 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200601 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000602 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200603 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200604 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000605
606 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200607 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000608
Gilles Peskine82204662018-09-11 18:43:09 +0200609 n = fread( buf, 1, sizeof( buf ), f );
610 if( fread( &c, 1, 1, f ) != 0 )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100611 {
Gilles Peskine82204662018-09-11 18:43:09 +0200612 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
613 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100614 }
Gilles Peskine82204662018-09-11 18:43:09 +0200615 if( n == 0 || ferror( f ) )
616 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100617 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200618 goto exit;
619 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000620 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200621 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200622
Gilles Peskine82204662018-09-11 18:43:09 +0200623 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
624
625exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500626 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200627 if( f != NULL )
628 fclose( f );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100629 if( ret != 0 )
630 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200631 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000632}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200633#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000634
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200635#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000636
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000637static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000638 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
639 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
640 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
641 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
642 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
643 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
644 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
645 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
646 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
647 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
648 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
649 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
650
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000651static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000652 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
653 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
654 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
655 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
656 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
657 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
658 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
659 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
660
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100661static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000662 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
663 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
664
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100665static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000666 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
667 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
668
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100669static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000670 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
671 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
672
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100673static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000674 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
675 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
676
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100677static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200678static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
679 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000680{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100681 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000682 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100683 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000684 return( 0 );
685}
686
Paul Bakker7dc4c442014-02-01 22:50:26 +0100687#define CHK( c ) if( (c) != 0 ) \
688 { \
689 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200690 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100691 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100692 }
693
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000694/*
695 * Checkup routine
696 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200697int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000698{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200699 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000700 unsigned char buf[16];
701
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200702 mbedtls_ctr_drbg_init( &ctx );
703
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000704 /*
705 * Based on a NIST CTR_DRBG test vector (PR = True)
706 */
707 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200708 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000709
710 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200711 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Hanno Beckera08651f2018-10-05 09:38:59 +0100712 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200713 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
714 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
715 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
716 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000717
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100718 mbedtls_ctr_drbg_free( &ctx );
719
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000720 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200721 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000722
723 /*
724 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
725 */
726 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200727 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000728
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100729 mbedtls_ctr_drbg_init( &ctx );
730
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000731 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200732 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Hanno Beckera08651f2018-10-05 09:38:59 +0100733 (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200734 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
735 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
736 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100737 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000738
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100739 mbedtls_ctr_drbg_free( &ctx );
740
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000741 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200742 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000743
744 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200745 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000746
747 return( 0 );
748}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200749#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000750
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200751#endif /* MBEDTLS_CTR_DRBG_C */