blob: 55953812136262b859e455e174021a19f7d9cdf5 [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 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300105 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
106 {
107 return( ret );
108 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000109
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200110 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300111 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000112 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300113 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000114 return( 0 );
115}
116
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200117int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker18d32912011-12-10 21:42:49 +0000118 int (*f_entropy)(void *, unsigned char *, size_t),
119 void *p_entropy,
120 const unsigned char *custom,
121 size_t len )
122{
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200123 return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy, custom, len,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200124 MBEDTLS_CTR_DRBG_ENTROPY_LEN ) );
Paul Bakker18d32912011-12-10 21:42:49 +0000125}
126
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200127void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
Paul Bakkerfff03662014-06-18 16:21:25 +0200128{
129 if( ctx == NULL )
130 return;
131
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100132#if defined(MBEDTLS_THREADING_C)
133 mbedtls_mutex_free( &ctx->mutex );
134#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200135 mbedtls_aes_free( &ctx->aes_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500136 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Paul Bakkerfff03662014-06-18 16:21:25 +0200137}
138
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200139void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000140{
141 ctx->prediction_resistance = resistance;
142}
143
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200144void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000145{
146 ctx->entropy_len = len;
147}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200148
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200149void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000150{
151 ctx->reseed_interval = interval;
152}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200153
154static int block_cipher_df( unsigned char *output,
155 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000156{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200157 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
158 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
159 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
160 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100161 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200162 mbedtls_aes_context aes_ctx;
Dvir Markovich1b364992017-06-26 13:43:34 +0300163 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000164
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200165 int i, j;
166 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000167
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200168 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
169 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100170
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200171 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
172 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000173
174 /*
175 * Construct IV (16 bytes) and S in buffer
176 * IV = Counter (in 32-bits) padded to 16 with zeroes
177 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
178 * data || 0x80
179 * (Total is padded to a multiple of 16-bytes with zeroes)
180 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200181 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000182 *p++ = ( data_len >> 24 ) & 0xff;
183 *p++ = ( data_len >> 16 ) & 0xff;
184 *p++ = ( data_len >> 8 ) & 0xff;
185 *p++ = ( data_len ) & 0xff;
186 p += 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200187 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000188 memcpy( p, data, data_len );
189 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000190
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200191 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000192
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200193 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000194 key[i] = i;
195
Dvir Markovich1b364992017-06-26 13:43:34 +0300196 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
197 {
198 goto exit;
199 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000200
201 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200202 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000203 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200204 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000205 {
206 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200207 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000208 use_len = buf_len;
209
210 while( use_len > 0 )
211 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200212 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000213 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200214 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
215 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
216 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000217
Dvir Markovich1b364992017-06-26 13:43:34 +0300218 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ) ) != 0 )
219 {
220 goto exit;
221 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000222 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200223
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200224 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000225
226 /*
227 * Update IV
228 */
229 buf[3]++;
230 }
231
232 /*
233 * Do final encryption with reduced data
234 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300235 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
236 {
237 goto exit;
238 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200239 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000240 p = output;
241
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200242 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000243 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300244 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) ) != 0 )
245 {
246 goto exit;
247 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200248 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
249 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000250 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300251exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200252 mbedtls_aes_free( &aes_ctx );
Dvir Markovich1b364992017-06-26 13:43:34 +0300253 /*
254 * tidy up the stack
255 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500256 mbedtls_platform_zeroize( buf, sizeof( buf ) );
257 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
258 mbedtls_platform_zeroize( key, sizeof( key ) );
259 mbedtls_platform_zeroize( chain, sizeof( chain ) );
Dvir Markovich1b364992017-06-26 13:43:34 +0300260 if( 0 != ret )
261 {
262 /*
263 * wipe partial seed from memory
264 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500265 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
Dvir Markovich1b364992017-06-26 13:43:34 +0300266 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200267
Dvir Markovich1b364992017-06-26 13:43:34 +0300268 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000269}
270
Gilles Peskineed7da592018-08-03 20:16:52 +0200271/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
272 * ctr_drbg_update_internal(ctx, provided_data)
273 * implements
274 * CTR_DRBG_Update(provided_data, Key, V)
275 * with inputs and outputs
276 * ctx->aes_ctx = Key
277 * ctx->counter = V
278 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200279static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
280 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000281{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200282 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000283 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000284 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300285 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000286
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200287 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000288
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200289 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000290 {
291 /*
292 * Increase counter
293 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200294 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000295 if( ++ctx->counter[i - 1] != 0 )
296 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000297
298 /*
299 * Crypt counter block
300 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300301 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 )
Gilles Peskinee495a8a2018-09-11 15:34:17 +0200302 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000303
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200304 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000305 }
306
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200307 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000308 tmp[i] ^= data[i];
309
310 /*
311 * Update key and counter
312 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300313 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Gilles Peskinee495a8a2018-09-11 15:34:17 +0200314 goto exit;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200315 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000316
Gilles Peskinee495a8a2018-09-11 15:34:17 +0200317exit:
318 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
319 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000320}
321
Gilles Peskineed7da592018-08-03 20:16:52 +0200322/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
323 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
324 * implements
325 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
326 * security_strength) -> initial_working_state
327 * with inputs
328 * ctx->counter = all-bits-0
329 * ctx->aes_ctx = context from all-bits-0 key
330 * additional[:add_len] = entropy_input || nonce || personalization_string
331 * and with outputs
332 * ctx = initial_working_state
333 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200334void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000335 const unsigned char *additional, size_t add_len )
336{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200337 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000338
339 if( add_len > 0 )
340 {
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100341 /* MAX_INPUT would be more logical here, but we have to match
342 * block_cipher_df()'s limits since we can't propagate errors */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200343 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
344 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100345
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000346 block_cipher_df( add_input, additional, add_len );
347 ctr_drbg_update_internal( ctx, add_input );
Gilles Peskinee495a8a2018-09-11 15:34:17 +0200348 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000349 }
350}
351
Gilles Peskineed7da592018-08-03 20:16:52 +0200352/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
353 * mbedtls_ctr_drbg_reseed(ctx, additional, len)
354 * implements
355 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
356 * -> new_working_state
357 * with inputs
358 * ctx contains working_state
359 * additional[:len] = additional_input
360 * and entropy_input comes from calling ctx->f_entropy
361 * and with output
362 * ctx contains new_working_state
363 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200364int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000365 const unsigned char *additional, size_t len )
366{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200367 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000368 size_t seedlen = 0;
Dvir Markovich1b364992017-06-26 13:43:34 +0300369 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000370
Andres Amaya Garcia6a543362017-01-17 23:04:22 +0000371 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
372 len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200373 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000374
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200375 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000376
377 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200378 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000379 */
380 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
381 ctx->entropy_len ) )
382 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200383 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000384 }
385
386 seedlen += ctx->entropy_len;
387
388 /*
389 * Add additional data
390 */
391 if( additional && len )
392 {
393 memcpy( seed + seedlen, additional, len );
394 seedlen += len;
395 }
396
397 /*
398 * Reduce to 384 bits
399 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300400 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
Gilles Peskinee495a8a2018-09-11 15:34:17 +0200401 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000402
403 /*
404 * Update state
405 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300406 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
Gilles Peskinee495a8a2018-09-11 15:34:17 +0200407 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000408 ctx->reseed_counter = 1;
409
Gilles Peskinee495a8a2018-09-11 15:34:17 +0200410exit:
411 mbedtls_platform_zeroize( seed, sizeof( seed ) );
412 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000413}
Paul Bakker9af723c2014-05-01 13:03:14 +0200414
Gilles Peskineed7da592018-08-03 20:16:52 +0200415/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
416 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
417 * implements
418 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
419 * -> working_state_after_reseed
420 * if required, then
421 * CTR_DRBG_Generate(working_state_after_reseed,
422 * requested_number_of_bits, additional_input)
423 * -> status, returned_bits, new_working_state
424 * with inputs
425 * ctx contains working_state
426 * requested_number_of_bits = 8 * output_len
427 * additional[:add_len] = additional_input
428 * and entropy_input comes from calling ctx->f_entropy
429 * and with outputs
430 * status = SUCCESS (this function does the reseed internally)
431 * returned_bits = output[:output_len]
432 * ctx contains new_working_state
433 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200434int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000435 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000436 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000437{
438 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200439 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
440 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000441 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200442 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000443 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000444 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000445
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200446 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
447 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000448
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
450 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000451
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200452 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000453
454 if( ctx->reseed_counter > ctx->reseed_interval ||
455 ctx->prediction_resistance )
456 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200457 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300458 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000459 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300460 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000461 add_len = 0;
462 }
463
464 if( add_len > 0 )
465 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300466 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskinee495a8a2018-09-11 15:34:17 +0200467 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300468 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskinee495a8a2018-09-11 15:34:17 +0200469 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000470 }
471
472 while( output_len > 0 )
473 {
474 /*
475 * Increase counter
476 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200477 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000478 if( ++ctx->counter[i - 1] != 0 )
479 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000480
481 /*
482 * Crypt counter block
483 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300484 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 )
Gilles Peskinee495a8a2018-09-11 15:34:17 +0200485 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000486
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200487 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200488 output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000489 /*
490 * Copy random block to destination
491 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000492 memcpy( p, tmp, use_len );
493 p += use_len;
494 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000495 }
496
Dvir Markovich1b364992017-06-26 13:43:34 +0300497 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskinee495a8a2018-09-11 15:34:17 +0200498 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000499
500 ctx->reseed_counter++;
501
Gilles Peskinee495a8a2018-09-11 15:34:17 +0200502exit:
503 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
504 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000505 return( 0 );
506}
507
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200508int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000509{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100510 int ret;
511 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
512
513#if defined(MBEDTLS_THREADING_C)
514 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
515 return( ret );
516#endif
517
518 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
519
520#if defined(MBEDTLS_THREADING_C)
521 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
522 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
523#endif
524
525 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000526}
527
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200528#if defined(MBEDTLS_FS_IO)
529int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000530{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200531 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000532 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200533 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000534
535 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200536 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000537
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200538 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200539 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000540
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200541 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200542 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100543 else
544 ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000545
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100546exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500547 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200548
Paul Bakkerfc754a92011-12-05 13:23:51 +0000549 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200550 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000551}
552
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200553int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000554{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100555 int ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000556 FILE *f;
557 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200558 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000559
560 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200561 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000562
563 fseek( f, 0, SEEK_END );
564 n = (size_t) ftell( f );
565 fseek( f, 0, SEEK_SET );
566
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200567 if( n > MBEDTLS_CTR_DRBG_MAX_INPUT )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100568 {
569 fclose( f );
570 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
571 }
572
573 if( fread( buf, 1, n, f ) != n )
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100574 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
575 else
576 mbedtls_ctr_drbg_update( ctx, buf, n );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000577
Paul Bakkerfc754a92011-12-05 13:23:51 +0000578 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200579
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500580 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100581
582 if( ret != 0 )
583 return( ret );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200584
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200585 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000586}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200587#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000588
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200589#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000590
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000591static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000592 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
593 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
594 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
595 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
596 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
597 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
598 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
599 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
600 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
601 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
602 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
603 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
604
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000605static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000606 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
607 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
608 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
609 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
610 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
611 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
612 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
613 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
614
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100615static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000616 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
617 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
618
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100619static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000620 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
621 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
622
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100623static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000624 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
625 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
626
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100627static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000628 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
629 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
630
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100631static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200632static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
633 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000634{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100635 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000636 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100637 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000638 return( 0 );
639}
640
Paul Bakker7dc4c442014-02-01 22:50:26 +0100641#define CHK( c ) if( (c) != 0 ) \
642 { \
643 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200644 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100645 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100646 }
647
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000648/*
649 * Checkup routine
650 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200651int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000652{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200653 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000654 unsigned char buf[16];
655
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200656 mbedtls_ctr_drbg_init( &ctx );
657
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000658 /*
659 * Based on a NIST CTR_DRBG test vector (PR = True)
660 */
661 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200662 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000663
664 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200665 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000666 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200667 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
668 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
669 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
670 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000671
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100672 mbedtls_ctr_drbg_free( &ctx );
673
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000674 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200675 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000676
677 /*
678 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
679 */
680 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200681 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000682
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100683 mbedtls_ctr_drbg_init( &ctx );
684
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000685 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200686 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000687 (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200688 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
689 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
690 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100691 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000692
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100693 mbedtls_ctr_drbg_free( &ctx );
694
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000695 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200696 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000697
698 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200699 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000700
701 return( 0 );
702}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200703#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000704
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200705#endif /* MBEDTLS_CTR_DRBG_C */