blob: 54feb71c9966b64ec206532615a206854a32b537 [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/*
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020059 * CTR_DRBG context initialization
60 */
61void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
62{
63 memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010064
65#if defined(MBEDTLS_THREADING_C)
66 mbedtls_mutex_init( &ctx->mutex );
67#endif
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020068}
69
70/*
Paul Bakker18d32912011-12-10 21:42:49 +000071 * Non-public function wrapped by ctr_crbg_init(). Necessary to allow NIST
72 * tests to succeed (which require known length fixed entropy)
73 */
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020074int mbedtls_ctr_drbg_seed_entropy_len(
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020075 mbedtls_ctr_drbg_context *ctx,
Paul Bakker0e04d0e2011-11-27 14:46:59 +000076 int (*f_entropy)(void *, unsigned char *, size_t),
77 void *p_entropy,
Paul Bakker1bc9efc2011-12-03 11:29:32 +000078 const unsigned char *custom,
Paul Bakker18d32912011-12-10 21:42:49 +000079 size_t len,
80 size_t entropy_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000081{
82 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020083 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Paul Bakker0e04d0e2011-11-27 14:46:59 +000084
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020085 memset( ctx, 0, sizeof(mbedtls_ctr_drbg_context) );
86 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000087
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020088 mbedtls_aes_init( &ctx->aes_ctx );
Paul Bakkerc7ea99a2014-06-18 11:12:03 +020089
Paul Bakker0e04d0e2011-11-27 14:46:59 +000090 ctx->f_entropy = f_entropy;
91 ctx->p_entropy = p_entropy;
92
Paul Bakker18d32912011-12-10 21:42:49 +000093 ctx->entropy_len = entropy_len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020094 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
Paul Bakker0e04d0e2011-11-27 14:46:59 +000095
96 /*
97 * Initialize with an empty key
98 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020099 mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000100
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200101 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000102 return( ret );
103
104 return( 0 );
105}
106
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200107int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker18d32912011-12-10 21:42:49 +0000108 int (*f_entropy)(void *, unsigned char *, size_t),
109 void *p_entropy,
110 const unsigned char *custom,
111 size_t len )
112{
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200113 return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy, custom, len,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200114 MBEDTLS_CTR_DRBG_ENTROPY_LEN ) );
Paul Bakker18d32912011-12-10 21:42:49 +0000115}
116
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200117void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
Paul Bakkerfff03662014-06-18 16:21:25 +0200118{
119 if( ctx == NULL )
120 return;
121
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100122#if defined(MBEDTLS_THREADING_C)
123 mbedtls_mutex_free( &ctx->mutex );
124#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200125 mbedtls_aes_free( &ctx->aes_ctx );
126 mbedtls_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Paul Bakkerfff03662014-06-18 16:21:25 +0200127}
128
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200129void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000130{
131 ctx->prediction_resistance = resistance;
132}
133
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200134void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000135{
136 ctx->entropy_len = len;
137}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200138
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200139void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000140{
141 ctx->reseed_interval = interval;
142}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200143
144static int block_cipher_df( unsigned char *output,
145 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000146{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200147 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
148 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
149 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
150 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100151 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200152 mbedtls_aes_context aes_ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000153
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200154 int i, j;
155 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000156
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200157 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
158 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100159
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200160 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
161 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000162
163 /*
164 * Construct IV (16 bytes) and S in buffer
165 * IV = Counter (in 32-bits) padded to 16 with zeroes
166 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
167 * data || 0x80
168 * (Total is padded to a multiple of 16-bytes with zeroes)
169 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200170 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000171 *p++ = ( data_len >> 24 ) & 0xff;
172 *p++ = ( data_len >> 16 ) & 0xff;
173 *p++ = ( data_len >> 8 ) & 0xff;
174 *p++ = ( data_len ) & 0xff;
175 p += 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200176 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000177 memcpy( p, data, data_len );
178 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000179
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200180 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000181
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200182 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000183 key[i] = i;
184
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200185 mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000186
187 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200188 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000189 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200190 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000191 {
192 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200193 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000194 use_len = buf_len;
195
196 while( use_len > 0 )
197 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200198 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000199 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200200 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
201 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
202 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000203
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200204 mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000205 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200206
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200207 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000208
209 /*
210 * Update IV
211 */
212 buf[3]++;
213 }
214
215 /*
216 * Do final encryption with reduced data
217 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200218 mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS );
219 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000220 p = output;
221
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200222 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000223 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200224 mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
225 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
226 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000227 }
228
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200229 mbedtls_aes_free( &aes_ctx );
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200230
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000231 return( 0 );
232}
233
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200234static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
235 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000236{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200237 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000238 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000239 int i, j;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000240
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200241 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000242
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200243 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000244 {
245 /*
246 * Increase counter
247 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200248 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000249 if( ++ctx->counter[i - 1] != 0 )
250 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000251
252 /*
253 * Crypt counter block
254 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200255 mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000256
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200257 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000258 }
259
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200260 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000261 tmp[i] ^= data[i];
262
263 /*
264 * Update key and counter
265 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200266 mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS );
267 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000268
269 return( 0 );
270}
271
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200272void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000273 const unsigned char *additional, size_t add_len )
274{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200275 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000276
277 if( add_len > 0 )
278 {
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100279 /* MAX_INPUT would be more logical here, but we have to match
280 * block_cipher_df()'s limits since we can't propagate errors */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200281 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
282 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100283
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000284 block_cipher_df( add_input, additional, add_len );
285 ctr_drbg_update_internal( ctx, add_input );
286 }
287}
288
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200289int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000290 const unsigned char *additional, size_t len )
291{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200292 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000293 size_t seedlen = 0;
294
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200295 if( ctx->entropy_len + len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
296 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000297
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200298 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000299
300 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200301 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000302 */
303 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
304 ctx->entropy_len ) )
305 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200306 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000307 }
308
309 seedlen += ctx->entropy_len;
310
311 /*
312 * Add additional data
313 */
314 if( additional && len )
315 {
316 memcpy( seed + seedlen, additional, len );
317 seedlen += len;
318 }
319
320 /*
321 * Reduce to 384 bits
322 */
323 block_cipher_df( seed, seed, seedlen );
324
325 /*
326 * Update state
327 */
328 ctr_drbg_update_internal( ctx, seed );
329 ctx->reseed_counter = 1;
330
331 return( 0 );
332}
Paul Bakker9af723c2014-05-01 13:03:14 +0200333
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200334int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000335 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000336 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000337{
338 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200339 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
340 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000341 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200342 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000343 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000344 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000345
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200346 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
347 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000348
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200349 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
350 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000351
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200352 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000353
354 if( ctx->reseed_counter > ctx->reseed_interval ||
355 ctx->prediction_resistance )
356 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200357 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000358 return( ret );
359
360 add_len = 0;
361 }
362
363 if( add_len > 0 )
364 {
365 block_cipher_df( add_input, additional, add_len );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000366 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000367 }
368
369 while( output_len > 0 )
370 {
371 /*
372 * Increase counter
373 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200374 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000375 if( ++ctx->counter[i - 1] != 0 )
376 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000377
378 /*
379 * Crypt counter block
380 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200381 mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000382
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200383 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200384 output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000385 /*
386 * Copy random block to destination
387 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000388 memcpy( p, tmp, use_len );
389 p += use_len;
390 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000391 }
392
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000393 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000394
395 ctx->reseed_counter++;
396
397 return( 0 );
398}
399
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200400int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000401{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100402 int ret;
403 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
404
405#if defined(MBEDTLS_THREADING_C)
406 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
407 return( ret );
408#endif
409
410 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
411
412#if defined(MBEDTLS_THREADING_C)
413 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
414 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
415#endif
416
417 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000418}
419
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200420#if defined(MBEDTLS_FS_IO)
421int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000422{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200423 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000424 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200425 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000426
427 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200428 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000429
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200430 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200431 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000432
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200433 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000434 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200435 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakker4c284c92014-03-26 15:33:05 +0100436 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000437 }
438
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200439 ret = 0;
440
441exit:
Paul Bakkerfc754a92011-12-05 13:23:51 +0000442 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200443 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000444}
445
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200446int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000447{
448 FILE *f;
449 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200450 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000451
452 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200453 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000454
455 fseek( f, 0, SEEK_END );
456 n = (size_t) ftell( f );
457 fseek( f, 0, SEEK_SET );
458
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200459 if( n > MBEDTLS_CTR_DRBG_MAX_INPUT )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200460 {
461 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200463 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000464
465 if( fread( buf, 1, n, f ) != n )
466 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100467 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200468 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000469 }
470
Paul Bakkerfc754a92011-12-05 13:23:51 +0000471 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200472
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200473 mbedtls_ctr_drbg_update( ctx, buf, n );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200474
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200475 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000476}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200477#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000478
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200479#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000480
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000481static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000482 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
483 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
484 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
485 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
486 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
487 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
488 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
489 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
490 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
491 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
492 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
493 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
494
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000495static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000496 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
497 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
498 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
499 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
500 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
501 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
502 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
503 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
504
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100505static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000506 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
507 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
508
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100509static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000510 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
511 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
512
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100513static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000514 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
515 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
516
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100517static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000518 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
519 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
520
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100521static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200522static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
523 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000524{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100525 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000526 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100527 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000528 return( 0 );
529}
530
Paul Bakker7dc4c442014-02-01 22:50:26 +0100531#define CHK( c ) if( (c) != 0 ) \
532 { \
533 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200534 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100535 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100536 }
537
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000538/*
539 * Checkup routine
540 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200541int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000542{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200543 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000544 unsigned char buf[16];
545
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200546 mbedtls_ctr_drbg_init( &ctx );
547
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000548 /*
549 * Based on a NIST CTR_DRBG test vector (PR = True)
550 */
551 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200552 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000553
554 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200555 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000556 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200557 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
558 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
559 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
560 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000561
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100562 mbedtls_ctr_drbg_free( &ctx );
563
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000564 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200565 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000566
567 /*
568 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
569 */
570 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200571 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000572
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100573 mbedtls_ctr_drbg_init( &ctx );
574
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000575 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200576 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000577 (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200578 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
579 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
580 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100581 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000582
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100583 mbedtls_ctr_drbg_free( &ctx );
584
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000585 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200586 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000587
588 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200589 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000590
591 return( 0 );
592}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200593#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000594
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200595#endif /* MBEDTLS_CTR_DRBG_C */