blob: 355d0f4f49313315a71651a982a41ef180ba676d [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é-Gonnarda658a402015-01-23 09:45:19 +00004 * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
Paul Bakker0e04d0e2011-11-27 14:46:59 +00005 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +00006 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker0e04d0e2011-11-27 14:46:59 +00007 *
Paul Bakker0e04d0e2011-11-27 14:46:59 +00008 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22/*
23 * The NIST SP 800-90 DRBGs are described in the following publucation.
24 *
25 * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
26 */
27
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020028#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000029#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020030#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020031#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020032#endif
Paul Bakker0e04d0e2011-11-27 14:46:59 +000033
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020034#if defined(MBEDTLS_CTR_DRBG_C)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000035
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000036#include "mbedtls/ctr_drbg.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 Bakkerfff03662014-06-18 16:21:25 +020053/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020054static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakkerfff03662014-06-18 16:21:25 +020055 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
56}
57
Paul Bakker18d32912011-12-10 21:42:49 +000058/*
59 * Non-public function wrapped by ctr_crbg_init(). Necessary to allow NIST
60 * tests to succeed (which require known length fixed entropy)
61 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020062int mbedtls_ctr_drbg_init_entropy_len(
63 mbedtls_ctr_drbg_context *ctx,
Paul Bakker0e04d0e2011-11-27 14:46:59 +000064 int (*f_entropy)(void *, unsigned char *, size_t),
65 void *p_entropy,
Paul Bakker1bc9efc2011-12-03 11:29:32 +000066 const unsigned char *custom,
Paul Bakker18d32912011-12-10 21:42:49 +000067 size_t len,
68 size_t entropy_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000069{
70 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020071 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Paul Bakker0e04d0e2011-11-27 14:46:59 +000072
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020073 memset( ctx, 0, sizeof(mbedtls_ctr_drbg_context) );
74 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000075
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020076 mbedtls_aes_init( &ctx->aes_ctx );
Paul Bakkerc7ea99a2014-06-18 11:12:03 +020077
Paul Bakker0e04d0e2011-11-27 14:46:59 +000078 ctx->f_entropy = f_entropy;
79 ctx->p_entropy = p_entropy;
80
Paul Bakker18d32912011-12-10 21:42:49 +000081 ctx->entropy_len = entropy_len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020082 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
Paul Bakker0e04d0e2011-11-27 14:46:59 +000083
84 /*
85 * Initialize with an empty key
86 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020087 mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000088
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020089 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000090 return( ret );
91
92 return( 0 );
93}
94
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020095int mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx,
Paul Bakker18d32912011-12-10 21:42:49 +000096 int (*f_entropy)(void *, unsigned char *, size_t),
97 void *p_entropy,
98 const unsigned char *custom,
99 size_t len )
100{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200101 return( mbedtls_ctr_drbg_init_entropy_len( ctx, f_entropy, p_entropy, custom, len,
102 MBEDTLS_CTR_DRBG_ENTROPY_LEN ) );
Paul Bakker18d32912011-12-10 21:42:49 +0000103}
104
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200105void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
Paul Bakkerfff03662014-06-18 16:21:25 +0200106{
107 if( ctx == NULL )
108 return;
109
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200110 mbedtls_aes_free( &ctx->aes_ctx );
111 mbedtls_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Paul Bakkerfff03662014-06-18 16:21:25 +0200112}
113
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200114void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000115{
116 ctx->prediction_resistance = resistance;
117}
118
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200119void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000120{
121 ctx->entropy_len = len;
122}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200123
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200124void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000125{
126 ctx->reseed_interval = interval;
127}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200128
129static int block_cipher_df( unsigned char *output,
130 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000131{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200132 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
133 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
134 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
135 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100136 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200137 mbedtls_aes_context aes_ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000138
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200139 int i, j;
140 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000141
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200142 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
143 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100144
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200145 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
146 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000147
148 /*
149 * Construct IV (16 bytes) and S in buffer
150 * IV = Counter (in 32-bits) padded to 16 with zeroes
151 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
152 * data || 0x80
153 * (Total is padded to a multiple of 16-bytes with zeroes)
154 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200155 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000156 *p++ = ( data_len >> 24 ) & 0xff;
157 *p++ = ( data_len >> 16 ) & 0xff;
158 *p++ = ( data_len >> 8 ) & 0xff;
159 *p++ = ( data_len ) & 0xff;
160 p += 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200161 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000162 memcpy( p, data, data_len );
163 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000164
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200165 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000166
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200167 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000168 key[i] = i;
169
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200170 mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000171
172 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200173 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000174 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200175 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000176 {
177 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200178 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000179 use_len = buf_len;
180
181 while( use_len > 0 )
182 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200183 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000184 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200185 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
186 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
187 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000188
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200189 mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000190 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200191
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200192 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000193
194 /*
195 * Update IV
196 */
197 buf[3]++;
198 }
199
200 /*
201 * Do final encryption with reduced data
202 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200203 mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS );
204 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000205 p = output;
206
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200207 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000208 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200209 mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
210 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
211 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000212 }
213
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200214 mbedtls_aes_free( &aes_ctx );
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200215
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000216 return( 0 );
217}
218
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200219static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
220 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000221{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200222 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000223 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000224 int i, j;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000225
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200226 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000227
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200228 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000229 {
230 /*
231 * Increase counter
232 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200233 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000234 if( ++ctx->counter[i - 1] != 0 )
235 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000236
237 /*
238 * Crypt counter block
239 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200240 mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000241
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200242 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000243 }
244
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200245 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000246 tmp[i] ^= data[i];
247
248 /*
249 * Update key and counter
250 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200251 mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS );
252 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000253
254 return( 0 );
255}
256
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200257void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000258 const unsigned char *additional, size_t add_len )
259{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200260 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000261
262 if( add_len > 0 )
263 {
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100264 /* MAX_INPUT would be more logical here, but we have to match
265 * block_cipher_df()'s limits since we can't propagate errors */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200266 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
267 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100268
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000269 block_cipher_df( add_input, additional, add_len );
270 ctr_drbg_update_internal( ctx, add_input );
271 }
272}
273
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200274int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000275 const unsigned char *additional, size_t len )
276{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200277 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000278 size_t seedlen = 0;
279
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200280 if( ctx->entropy_len + len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
281 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000282
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200283 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000284
285 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200286 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000287 */
288 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
289 ctx->entropy_len ) )
290 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200291 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000292 }
293
294 seedlen += ctx->entropy_len;
295
296 /*
297 * Add additional data
298 */
299 if( additional && len )
300 {
301 memcpy( seed + seedlen, additional, len );
302 seedlen += len;
303 }
304
305 /*
306 * Reduce to 384 bits
307 */
308 block_cipher_df( seed, seed, seedlen );
309
310 /*
311 * Update state
312 */
313 ctr_drbg_update_internal( ctx, seed );
314 ctx->reseed_counter = 1;
315
316 return( 0 );
317}
Paul Bakker9af723c2014-05-01 13:03:14 +0200318
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200319int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000320 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000321 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000322{
323 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200324 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
325 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000326 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200327 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000328 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000329 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000330
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200331 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
332 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000333
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200334 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
335 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000336
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200337 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000338
339 if( ctx->reseed_counter > ctx->reseed_interval ||
340 ctx->prediction_resistance )
341 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200342 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000343 return( ret );
344
345 add_len = 0;
346 }
347
348 if( add_len > 0 )
349 {
350 block_cipher_df( add_input, additional, add_len );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000351 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000352 }
353
354 while( output_len > 0 )
355 {
356 /*
357 * Increase counter
358 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200359 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000360 if( ++ctx->counter[i - 1] != 0 )
361 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000362
363 /*
364 * Crypt counter block
365 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200366 mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000367
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200368 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200369 output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000370 /*
371 * Copy random block to destination
372 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000373 memcpy( p, tmp, use_len );
374 p += use_len;
375 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000376 }
377
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000378 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000379
380 ctx->reseed_counter++;
381
382 return( 0 );
383}
384
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200385int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000386{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200387 return mbedtls_ctr_drbg_random_with_add( p_rng, output, output_len, NULL, 0 );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000388}
389
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200390#if defined(MBEDTLS_FS_IO)
391int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000392{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200393 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000394 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200395 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000396
397 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200398 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000399
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200400 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200401 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000402
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200403 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000404 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200405 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakker4c284c92014-03-26 15:33:05 +0100406 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000407 }
408
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200409 ret = 0;
410
411exit:
Paul Bakkerfc754a92011-12-05 13:23:51 +0000412 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200413 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000414}
415
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200416int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000417{
418 FILE *f;
419 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200420 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000421
422 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200423 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000424
425 fseek( f, 0, SEEK_END );
426 n = (size_t) ftell( f );
427 fseek( f, 0, SEEK_SET );
428
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200429 if( n > MBEDTLS_CTR_DRBG_MAX_INPUT )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200430 {
431 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200432 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200433 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000434
435 if( fread( buf, 1, n, f ) != n )
436 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100437 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200438 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000439 }
440
Paul Bakkerfc754a92011-12-05 13:23:51 +0000441 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200442
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200443 mbedtls_ctr_drbg_update( ctx, buf, n );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200444
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200445 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000446}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200447#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000448
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000450
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000451static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000452 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
453 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
454 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
455 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
456 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
457 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
458 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
459 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
460 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
461 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
462 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
463 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
464
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000465static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000466 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
467 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
468 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
469 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
470 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
471 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
472 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
473 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
474
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100475static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000476 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
477 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
478
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100479static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000480 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
481 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
482
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100483static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000484 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
485 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
486
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100487static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000488 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
489 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
490
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100491static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200492static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
493 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000494{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100495 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000496 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100497 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000498 return( 0 );
499}
500
Paul Bakker7dc4c442014-02-01 22:50:26 +0100501#define CHK( c ) if( (c) != 0 ) \
502 { \
503 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200504 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100505 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100506 }
507
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000508/*
509 * Checkup routine
510 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200511int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000512{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200513 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000514 unsigned char buf[16];
515
516 /*
517 * Based on a NIST CTR_DRBG test vector (PR = True)
518 */
519 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200520 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000521
522 test_offset = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200523 CHK( mbedtls_ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000524 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200525 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
526 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
527 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
528 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000529
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000530 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200531 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000532
533 /*
534 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
535 */
536 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200537 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000538
539 test_offset = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200540 CHK( mbedtls_ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000541 (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200542 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
543 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
544 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100545 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000546
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000547 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200548 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000549
550 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200551 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000552
553 return( 0 );
554}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200555#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000556
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200557#endif /* MBEDTLS_CTR_DRBG_C */