blob: 0655e765255eff642997ee4a65d68c36b6ffb72d [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 */
Gilles Peskine563a3332018-09-11 16:41:54 +0200334int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
335 const unsigned char *additional,
336 size_t add_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000337{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200338 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Gilles Peskine563a3332018-09-11 16:41:54 +0200339 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000340
Gilles Peskine563a3332018-09-11 16:41:54 +0200341 if( add_len == 0 )
342 return( 0 );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100343
Gilles Peskine563a3332018-09-11 16:41:54 +0200344 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
345 goto exit;
346 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
347 goto exit;
348
349exit:
350 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
351 return( ret );
352}
353
354/* Deprecated function, kept for backward compatibility. */
355void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
356 const unsigned char *additional,
357 size_t add_len )
358{
359 /* MAX_INPUT would be more logical here, but we have to match
360 * block_cipher_df()'s limits since we can't propagate errors */
361 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
362 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
363 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000364}
365
Gilles Peskineed7da592018-08-03 20:16:52 +0200366/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
367 * mbedtls_ctr_drbg_reseed(ctx, additional, len)
368 * implements
369 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
370 * -> new_working_state
371 * with inputs
372 * ctx contains working_state
373 * additional[:len] = additional_input
374 * and entropy_input comes from calling ctx->f_entropy
375 * and with output
376 * ctx contains new_working_state
377 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200378int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000379 const unsigned char *additional, size_t len )
380{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200381 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000382 size_t seedlen = 0;
Dvir Markovich1b364992017-06-26 13:43:34 +0300383 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000384
Andres Amaya Garcia6a543362017-01-17 23:04:22 +0000385 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
386 len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200387 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000388
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200389 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000390
391 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200392 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000393 */
394 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
395 ctx->entropy_len ) )
396 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200397 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000398 }
399
400 seedlen += ctx->entropy_len;
401
402 /*
403 * Add additional data
404 */
405 if( additional && len )
406 {
407 memcpy( seed + seedlen, additional, len );
408 seedlen += len;
409 }
410
411 /*
412 * Reduce to 384 bits
413 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300414 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
Gilles Peskinee495a8a2018-09-11 15:34:17 +0200415 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000416
417 /*
418 * Update state
419 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300420 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
Gilles Peskinee495a8a2018-09-11 15:34:17 +0200421 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000422 ctx->reseed_counter = 1;
423
Gilles Peskinee495a8a2018-09-11 15:34:17 +0200424exit:
425 mbedtls_platform_zeroize( seed, sizeof( seed ) );
426 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000427}
Paul Bakker9af723c2014-05-01 13:03:14 +0200428
Gilles Peskineed7da592018-08-03 20:16:52 +0200429/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
430 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
431 * implements
432 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
433 * -> working_state_after_reseed
434 * if required, then
435 * CTR_DRBG_Generate(working_state_after_reseed,
436 * requested_number_of_bits, additional_input)
437 * -> status, returned_bits, new_working_state
438 * with inputs
439 * ctx contains working_state
440 * requested_number_of_bits = 8 * output_len
441 * additional[:add_len] = additional_input
442 * and entropy_input comes from calling ctx->f_entropy
443 * and with outputs
444 * status = SUCCESS (this function does the reseed internally)
445 * returned_bits = output[:output_len]
446 * ctx contains new_working_state
447 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200448int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000449 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000450 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000451{
452 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200453 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
454 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000455 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200456 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000457 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000458 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000459
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200460 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
461 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000462
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200463 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
464 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000465
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200466 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000467
468 if( ctx->reseed_counter > ctx->reseed_interval ||
469 ctx->prediction_resistance )
470 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200471 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300472 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000473 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300474 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000475 add_len = 0;
476 }
477
478 if( add_len > 0 )
479 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300480 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskinee495a8a2018-09-11 15:34:17 +0200481 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300482 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskinee495a8a2018-09-11 15:34:17 +0200483 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000484 }
485
486 while( output_len > 0 )
487 {
488 /*
489 * Increase counter
490 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200491 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000492 if( ++ctx->counter[i - 1] != 0 )
493 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000494
495 /*
496 * Crypt counter block
497 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300498 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 )
Gilles Peskinee495a8a2018-09-11 15:34:17 +0200499 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000500
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200501 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200502 output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000503 /*
504 * Copy random block to destination
505 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000506 memcpy( p, tmp, use_len );
507 p += use_len;
508 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000509 }
510
Dvir Markovich1b364992017-06-26 13:43:34 +0300511 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskinee495a8a2018-09-11 15:34:17 +0200512 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000513
514 ctx->reseed_counter++;
515
Gilles Peskinee495a8a2018-09-11 15:34:17 +0200516exit:
517 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
518 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000519 return( 0 );
520}
521
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200522int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000523{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100524 int ret;
525 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
526
527#if defined(MBEDTLS_THREADING_C)
528 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
529 return( ret );
530#endif
531
532 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
533
534#if defined(MBEDTLS_THREADING_C)
535 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
536 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
537#endif
538
539 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000540}
541
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200542#if defined(MBEDTLS_FS_IO)
543int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000544{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200545 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000546 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200547 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000548
549 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200550 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000551
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200552 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200553 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000554
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200555 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200556 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100557 else
558 ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000559
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100560exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500561 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200562
Paul Bakkerfc754a92011-12-05 13:23:51 +0000563 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200564 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000565}
566
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200567int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000568{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100569 int ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000570 FILE *f;
571 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200572 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000573
574 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200575 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000576
577 fseek( f, 0, SEEK_END );
578 n = (size_t) ftell( f );
579 fseek( f, 0, SEEK_SET );
580
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200581 if( n > MBEDTLS_CTR_DRBG_MAX_INPUT )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100582 {
583 fclose( f );
584 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
585 }
586
587 if( fread( buf, 1, n, f ) != n )
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100588 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
589 else
Gilles Peskine563a3332018-09-11 16:41:54 +0200590 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000591
Paul Bakkerfc754a92011-12-05 13:23:51 +0000592 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200593
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500594 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100595
596 if( ret != 0 )
597 return( ret );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200598
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200599 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000600}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200601#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000602
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200603#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000604
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000605static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000606 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
607 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
608 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
609 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
610 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
611 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
612 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
613 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
614 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
615 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
616 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
617 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
618
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000619static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000620 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
621 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
622 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
623 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
624 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
625 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
626 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
627 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
628
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100629static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000630 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
631 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
632
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100633static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000634 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
635 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
636
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100637static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000638 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
639 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
640
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100641static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000642 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
643 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
644
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100645static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200646static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
647 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000648{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100649 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000650 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100651 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000652 return( 0 );
653}
654
Paul Bakker7dc4c442014-02-01 22:50:26 +0100655#define CHK( c ) if( (c) != 0 ) \
656 { \
657 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200658 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100659 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100660 }
661
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000662/*
663 * Checkup routine
664 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200665int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000666{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200667 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000668 unsigned char buf[16];
669
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200670 mbedtls_ctr_drbg_init( &ctx );
671
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000672 /*
673 * Based on a NIST CTR_DRBG test vector (PR = True)
674 */
675 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200676 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000677
678 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200679 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000680 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200681 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
682 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
683 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
684 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000685
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100686 mbedtls_ctr_drbg_free( &ctx );
687
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000688 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200689 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000690
691 /*
692 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
693 */
694 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200695 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000696
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100697 mbedtls_ctr_drbg_init( &ctx );
698
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000699 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200700 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000701 (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200702 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
703 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
704 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100705 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000706
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100707 mbedtls_ctr_drbg_free( &ctx );
708
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000709 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200710 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000711
712 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200713 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000714
715 return( 0 );
716}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200717#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000718
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200719#endif /* MBEDTLS_CTR_DRBG_C */