mbed TLS library

Dependents:   HTTPClient-SSL WS_SERVER

Committer:
ansond
Date:
Thu Jun 11 03:27:03 2015 +0000
Revision:
0:137634ff4186
initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ansond 0:137634ff4186 1 /*
ansond 0:137634ff4186 2 * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
ansond 0:137634ff4186 3 *
ansond 0:137634ff4186 4 * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
ansond 0:137634ff4186 5 *
ansond 0:137634ff4186 6 * This file is part of mbed TLS (https://tls.mbed.org)
ansond 0:137634ff4186 7 *
ansond 0:137634ff4186 8 * This program is free software; you can redistribute it and/or modify
ansond 0:137634ff4186 9 * it under the terms of the GNU General Public License as published by
ansond 0:137634ff4186 10 * the Free Software Foundation; either version 2 of the License, or
ansond 0:137634ff4186 11 * (at your option) any later version.
ansond 0:137634ff4186 12 *
ansond 0:137634ff4186 13 * This program is distributed in the hope that it will be useful,
ansond 0:137634ff4186 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ansond 0:137634ff4186 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
ansond 0:137634ff4186 16 * GNU General Public License for more details.
ansond 0:137634ff4186 17 *
ansond 0:137634ff4186 18 * You should have received a copy of the GNU General Public License along
ansond 0:137634ff4186 19 * with this program; if not, write to the Free Software Foundation, Inc.,
ansond 0:137634ff4186 20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
ansond 0:137634ff4186 21 */
ansond 0:137634ff4186 22 /*
ansond 0:137634ff4186 23 * The NIST SP 800-90 DRBGs are described in the following publucation.
ansond 0:137634ff4186 24 *
ansond 0:137634ff4186 25 * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
ansond 0:137634ff4186 26 */
ansond 0:137634ff4186 27
ansond 0:137634ff4186 28 #if !defined(POLARSSL_CONFIG_FILE)
ansond 0:137634ff4186 29 #include "polarssl/config.h"
ansond 0:137634ff4186 30 #else
ansond 0:137634ff4186 31 #include POLARSSL_CONFIG_FILE
ansond 0:137634ff4186 32 #endif
ansond 0:137634ff4186 33
ansond 0:137634ff4186 34 #if defined(POLARSSL_CTR_DRBG_C)
ansond 0:137634ff4186 35
ansond 0:137634ff4186 36 #include "polarssl/ctr_drbg.h"
ansond 0:137634ff4186 37
ansond 0:137634ff4186 38 #include <string.h>
ansond 0:137634ff4186 39
ansond 0:137634ff4186 40 #if defined(POLARSSL_FS_IO)
ansond 0:137634ff4186 41 #include <stdio.h>
ansond 0:137634ff4186 42 #endif
ansond 0:137634ff4186 43
ansond 0:137634ff4186 44 #if defined(POLARSSL_SELF_TEST)
ansond 0:137634ff4186 45 #if defined(POLARSSL_PLATFORM_C)
ansond 0:137634ff4186 46 #include "polarssl/platform.h"
ansond 0:137634ff4186 47 #else
ansond 0:137634ff4186 48 #include <stdio.h>
ansond 0:137634ff4186 49 #define polarssl_printf printf
ansond 0:137634ff4186 50 #endif /* POLARSSL_PLATFORM_C */
ansond 0:137634ff4186 51 #endif /* POLARSSL_SELF_TEST */
ansond 0:137634ff4186 52
ansond 0:137634ff4186 53 /* Implementation that should never be optimized out by the compiler */
ansond 0:137634ff4186 54 static void polarssl_zeroize( void *v, size_t n ) {
ansond 0:137634ff4186 55 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
ansond 0:137634ff4186 56 }
ansond 0:137634ff4186 57
ansond 0:137634ff4186 58 /*
ansond 0:137634ff4186 59 * Non-public function wrapped by ctr_crbg_init(). Necessary to allow NIST
ansond 0:137634ff4186 60 * tests to succeed (which require known length fixed entropy)
ansond 0:137634ff4186 61 */
ansond 0:137634ff4186 62 int ctr_drbg_init_entropy_len(
ansond 0:137634ff4186 63 ctr_drbg_context *ctx,
ansond 0:137634ff4186 64 int (*f_entropy)(void *, unsigned char *, size_t),
ansond 0:137634ff4186 65 void *p_entropy,
ansond 0:137634ff4186 66 const unsigned char *custom,
ansond 0:137634ff4186 67 size_t len,
ansond 0:137634ff4186 68 size_t entropy_len )
ansond 0:137634ff4186 69 {
ansond 0:137634ff4186 70 int ret;
ansond 0:137634ff4186 71 unsigned char key[CTR_DRBG_KEYSIZE];
ansond 0:137634ff4186 72
ansond 0:137634ff4186 73 memset( ctx, 0, sizeof(ctr_drbg_context) );
ansond 0:137634ff4186 74 memset( key, 0, CTR_DRBG_KEYSIZE );
ansond 0:137634ff4186 75
ansond 0:137634ff4186 76 aes_init( &ctx->aes_ctx );
ansond 0:137634ff4186 77
ansond 0:137634ff4186 78 ctx->f_entropy = f_entropy;
ansond 0:137634ff4186 79 ctx->p_entropy = p_entropy;
ansond 0:137634ff4186 80
ansond 0:137634ff4186 81 ctx->entropy_len = entropy_len;
ansond 0:137634ff4186 82 ctx->reseed_interval = CTR_DRBG_RESEED_INTERVAL;
ansond 0:137634ff4186 83
ansond 0:137634ff4186 84 /*
ansond 0:137634ff4186 85 * Initialize with an empty key
ansond 0:137634ff4186 86 */
ansond 0:137634ff4186 87 aes_setkey_enc( &ctx->aes_ctx, key, CTR_DRBG_KEYBITS );
ansond 0:137634ff4186 88
ansond 0:137634ff4186 89 if( ( ret = ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
ansond 0:137634ff4186 90 return( ret );
ansond 0:137634ff4186 91
ansond 0:137634ff4186 92 return( 0 );
ansond 0:137634ff4186 93 }
ansond 0:137634ff4186 94
ansond 0:137634ff4186 95 int ctr_drbg_init( ctr_drbg_context *ctx,
ansond 0:137634ff4186 96 int (*f_entropy)(void *, unsigned char *, size_t),
ansond 0:137634ff4186 97 void *p_entropy,
ansond 0:137634ff4186 98 const unsigned char *custom,
ansond 0:137634ff4186 99 size_t len )
ansond 0:137634ff4186 100 {
ansond 0:137634ff4186 101 return( ctr_drbg_init_entropy_len( ctx, f_entropy, p_entropy, custom, len,
ansond 0:137634ff4186 102 CTR_DRBG_ENTROPY_LEN ) );
ansond 0:137634ff4186 103 }
ansond 0:137634ff4186 104
ansond 0:137634ff4186 105 void ctr_drbg_free( ctr_drbg_context *ctx )
ansond 0:137634ff4186 106 {
ansond 0:137634ff4186 107 if( ctx == NULL )
ansond 0:137634ff4186 108 return;
ansond 0:137634ff4186 109
ansond 0:137634ff4186 110 aes_free( &ctx->aes_ctx );
ansond 0:137634ff4186 111 polarssl_zeroize( ctx, sizeof( ctr_drbg_context ) );
ansond 0:137634ff4186 112 }
ansond 0:137634ff4186 113
ansond 0:137634ff4186 114 void ctr_drbg_set_prediction_resistance( ctr_drbg_context *ctx, int resistance )
ansond 0:137634ff4186 115 {
ansond 0:137634ff4186 116 ctx->prediction_resistance = resistance;
ansond 0:137634ff4186 117 }
ansond 0:137634ff4186 118
ansond 0:137634ff4186 119 void ctr_drbg_set_entropy_len( ctr_drbg_context *ctx, size_t len )
ansond 0:137634ff4186 120 {
ansond 0:137634ff4186 121 ctx->entropy_len = len;
ansond 0:137634ff4186 122 }
ansond 0:137634ff4186 123
ansond 0:137634ff4186 124 void ctr_drbg_set_reseed_interval( ctr_drbg_context *ctx, int interval )
ansond 0:137634ff4186 125 {
ansond 0:137634ff4186 126 ctx->reseed_interval = interval;
ansond 0:137634ff4186 127 }
ansond 0:137634ff4186 128
ansond 0:137634ff4186 129 static int block_cipher_df( unsigned char *output,
ansond 0:137634ff4186 130 const unsigned char *data, size_t data_len )
ansond 0:137634ff4186 131 {
ansond 0:137634ff4186 132 unsigned char buf[CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16];
ansond 0:137634ff4186 133 unsigned char tmp[CTR_DRBG_SEEDLEN];
ansond 0:137634ff4186 134 unsigned char key[CTR_DRBG_KEYSIZE];
ansond 0:137634ff4186 135 unsigned char chain[CTR_DRBG_BLOCKSIZE];
ansond 0:137634ff4186 136 unsigned char *p, *iv;
ansond 0:137634ff4186 137 aes_context aes_ctx;
ansond 0:137634ff4186 138
ansond 0:137634ff4186 139 int i, j;
ansond 0:137634ff4186 140 size_t buf_len, use_len;
ansond 0:137634ff4186 141
ansond 0:137634ff4186 142 if( data_len > CTR_DRBG_MAX_SEED_INPUT )
ansond 0:137634ff4186 143 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
ansond 0:137634ff4186 144
ansond 0:137634ff4186 145 memset( buf, 0, CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16 );
ansond 0:137634ff4186 146 aes_init( &aes_ctx );
ansond 0:137634ff4186 147
ansond 0:137634ff4186 148 /*
ansond 0:137634ff4186 149 * Construct IV (16 bytes) and S in buffer
ansond 0:137634ff4186 150 * IV = Counter (in 32-bits) padded to 16 with zeroes
ansond 0:137634ff4186 151 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
ansond 0:137634ff4186 152 * data || 0x80
ansond 0:137634ff4186 153 * (Total is padded to a multiple of 16-bytes with zeroes)
ansond 0:137634ff4186 154 */
ansond 0:137634ff4186 155 p = buf + CTR_DRBG_BLOCKSIZE;
ansond 0:137634ff4186 156 *p++ = ( data_len >> 24 ) & 0xff;
ansond 0:137634ff4186 157 *p++ = ( data_len >> 16 ) & 0xff;
ansond 0:137634ff4186 158 *p++ = ( data_len >> 8 ) & 0xff;
ansond 0:137634ff4186 159 *p++ = ( data_len ) & 0xff;
ansond 0:137634ff4186 160 p += 3;
ansond 0:137634ff4186 161 *p++ = CTR_DRBG_SEEDLEN;
ansond 0:137634ff4186 162 memcpy( p, data, data_len );
ansond 0:137634ff4186 163 p[data_len] = 0x80;
ansond 0:137634ff4186 164
ansond 0:137634ff4186 165 buf_len = CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
ansond 0:137634ff4186 166
ansond 0:137634ff4186 167 for( i = 0; i < CTR_DRBG_KEYSIZE; i++ )
ansond 0:137634ff4186 168 key[i] = i;
ansond 0:137634ff4186 169
ansond 0:137634ff4186 170 aes_setkey_enc( &aes_ctx, key, CTR_DRBG_KEYBITS );
ansond 0:137634ff4186 171
ansond 0:137634ff4186 172 /*
ansond 0:137634ff4186 173 * Reduce data to POLARSSL_CTR_DRBG_SEEDLEN bytes of data
ansond 0:137634ff4186 174 */
ansond 0:137634ff4186 175 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
ansond 0:137634ff4186 176 {
ansond 0:137634ff4186 177 p = buf;
ansond 0:137634ff4186 178 memset( chain, 0, CTR_DRBG_BLOCKSIZE );
ansond 0:137634ff4186 179 use_len = buf_len;
ansond 0:137634ff4186 180
ansond 0:137634ff4186 181 while( use_len > 0 )
ansond 0:137634ff4186 182 {
ansond 0:137634ff4186 183 for( i = 0; i < CTR_DRBG_BLOCKSIZE; i++ )
ansond 0:137634ff4186 184 chain[i] ^= p[i];
ansond 0:137634ff4186 185 p += CTR_DRBG_BLOCKSIZE;
ansond 0:137634ff4186 186 use_len -= ( use_len >= CTR_DRBG_BLOCKSIZE ) ?
ansond 0:137634ff4186 187 CTR_DRBG_BLOCKSIZE : use_len;
ansond 0:137634ff4186 188
ansond 0:137634ff4186 189 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, chain, chain );
ansond 0:137634ff4186 190 }
ansond 0:137634ff4186 191
ansond 0:137634ff4186 192 memcpy( tmp + j, chain, CTR_DRBG_BLOCKSIZE );
ansond 0:137634ff4186 193
ansond 0:137634ff4186 194 /*
ansond 0:137634ff4186 195 * Update IV
ansond 0:137634ff4186 196 */
ansond 0:137634ff4186 197 buf[3]++;
ansond 0:137634ff4186 198 }
ansond 0:137634ff4186 199
ansond 0:137634ff4186 200 /*
ansond 0:137634ff4186 201 * Do final encryption with reduced data
ansond 0:137634ff4186 202 */
ansond 0:137634ff4186 203 aes_setkey_enc( &aes_ctx, tmp, CTR_DRBG_KEYBITS );
ansond 0:137634ff4186 204 iv = tmp + CTR_DRBG_KEYSIZE;
ansond 0:137634ff4186 205 p = output;
ansond 0:137634ff4186 206
ansond 0:137634ff4186 207 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
ansond 0:137634ff4186 208 {
ansond 0:137634ff4186 209 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, iv, iv );
ansond 0:137634ff4186 210 memcpy( p, iv, CTR_DRBG_BLOCKSIZE );
ansond 0:137634ff4186 211 p += CTR_DRBG_BLOCKSIZE;
ansond 0:137634ff4186 212 }
ansond 0:137634ff4186 213
ansond 0:137634ff4186 214 aes_free( &aes_ctx );
ansond 0:137634ff4186 215
ansond 0:137634ff4186 216 return( 0 );
ansond 0:137634ff4186 217 }
ansond 0:137634ff4186 218
ansond 0:137634ff4186 219 static int ctr_drbg_update_internal( ctr_drbg_context *ctx,
ansond 0:137634ff4186 220 const unsigned char data[CTR_DRBG_SEEDLEN] )
ansond 0:137634ff4186 221 {
ansond 0:137634ff4186 222 unsigned char tmp[CTR_DRBG_SEEDLEN];
ansond 0:137634ff4186 223 unsigned char *p = tmp;
ansond 0:137634ff4186 224 int i, j;
ansond 0:137634ff4186 225
ansond 0:137634ff4186 226 memset( tmp, 0, CTR_DRBG_SEEDLEN );
ansond 0:137634ff4186 227
ansond 0:137634ff4186 228 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
ansond 0:137634ff4186 229 {
ansond 0:137634ff4186 230 /*
ansond 0:137634ff4186 231 * Increase counter
ansond 0:137634ff4186 232 */
ansond 0:137634ff4186 233 for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
ansond 0:137634ff4186 234 if( ++ctx->counter[i - 1] != 0 )
ansond 0:137634ff4186 235 break;
ansond 0:137634ff4186 236
ansond 0:137634ff4186 237 /*
ansond 0:137634ff4186 238 * Crypt counter block
ansond 0:137634ff4186 239 */
ansond 0:137634ff4186 240 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, p );
ansond 0:137634ff4186 241
ansond 0:137634ff4186 242 p += CTR_DRBG_BLOCKSIZE;
ansond 0:137634ff4186 243 }
ansond 0:137634ff4186 244
ansond 0:137634ff4186 245 for( i = 0; i < CTR_DRBG_SEEDLEN; i++ )
ansond 0:137634ff4186 246 tmp[i] ^= data[i];
ansond 0:137634ff4186 247
ansond 0:137634ff4186 248 /*
ansond 0:137634ff4186 249 * Update key and counter
ansond 0:137634ff4186 250 */
ansond 0:137634ff4186 251 aes_setkey_enc( &ctx->aes_ctx, tmp, CTR_DRBG_KEYBITS );
ansond 0:137634ff4186 252 memcpy( ctx->counter, tmp + CTR_DRBG_KEYSIZE, CTR_DRBG_BLOCKSIZE );
ansond 0:137634ff4186 253
ansond 0:137634ff4186 254 return( 0 );
ansond 0:137634ff4186 255 }
ansond 0:137634ff4186 256
ansond 0:137634ff4186 257 void ctr_drbg_update( ctr_drbg_context *ctx,
ansond 0:137634ff4186 258 const unsigned char *additional, size_t add_len )
ansond 0:137634ff4186 259 {
ansond 0:137634ff4186 260 unsigned char add_input[CTR_DRBG_SEEDLEN];
ansond 0:137634ff4186 261
ansond 0:137634ff4186 262 if( add_len > 0 )
ansond 0:137634ff4186 263 {
ansond 0:137634ff4186 264 /* MAX_INPUT would be more logical here, but we have to match
ansond 0:137634ff4186 265 * block_cipher_df()'s limits since we can't propagate errors */
ansond 0:137634ff4186 266 if( add_len > CTR_DRBG_MAX_SEED_INPUT )
ansond 0:137634ff4186 267 add_len = CTR_DRBG_MAX_SEED_INPUT;
ansond 0:137634ff4186 268
ansond 0:137634ff4186 269 block_cipher_df( add_input, additional, add_len );
ansond 0:137634ff4186 270 ctr_drbg_update_internal( ctx, add_input );
ansond 0:137634ff4186 271 }
ansond 0:137634ff4186 272 }
ansond 0:137634ff4186 273
ansond 0:137634ff4186 274 int ctr_drbg_reseed( ctr_drbg_context *ctx,
ansond 0:137634ff4186 275 const unsigned char *additional, size_t len )
ansond 0:137634ff4186 276 {
ansond 0:137634ff4186 277 unsigned char seed[CTR_DRBG_MAX_SEED_INPUT];
ansond 0:137634ff4186 278 size_t seedlen = 0;
ansond 0:137634ff4186 279
ansond 0:137634ff4186 280 if( ctx->entropy_len + len > CTR_DRBG_MAX_SEED_INPUT )
ansond 0:137634ff4186 281 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
ansond 0:137634ff4186 282
ansond 0:137634ff4186 283 memset( seed, 0, CTR_DRBG_MAX_SEED_INPUT );
ansond 0:137634ff4186 284
ansond 0:137634ff4186 285 /*
ansond 0:137634ff4186 286 * Gather entropy_len bytes of entropy to seed state
ansond 0:137634ff4186 287 */
ansond 0:137634ff4186 288 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
ansond 0:137634ff4186 289 ctx->entropy_len ) )
ansond 0:137634ff4186 290 {
ansond 0:137634ff4186 291 return( POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
ansond 0:137634ff4186 292 }
ansond 0:137634ff4186 293
ansond 0:137634ff4186 294 seedlen += ctx->entropy_len;
ansond 0:137634ff4186 295
ansond 0:137634ff4186 296 /*
ansond 0:137634ff4186 297 * Add additional data
ansond 0:137634ff4186 298 */
ansond 0:137634ff4186 299 if( additional && len )
ansond 0:137634ff4186 300 {
ansond 0:137634ff4186 301 memcpy( seed + seedlen, additional, len );
ansond 0:137634ff4186 302 seedlen += len;
ansond 0:137634ff4186 303 }
ansond 0:137634ff4186 304
ansond 0:137634ff4186 305 /*
ansond 0:137634ff4186 306 * Reduce to 384 bits
ansond 0:137634ff4186 307 */
ansond 0:137634ff4186 308 block_cipher_df( seed, seed, seedlen );
ansond 0:137634ff4186 309
ansond 0:137634ff4186 310 /*
ansond 0:137634ff4186 311 * Update state
ansond 0:137634ff4186 312 */
ansond 0:137634ff4186 313 ctr_drbg_update_internal( ctx, seed );
ansond 0:137634ff4186 314 ctx->reseed_counter = 1;
ansond 0:137634ff4186 315
ansond 0:137634ff4186 316 return( 0 );
ansond 0:137634ff4186 317 }
ansond 0:137634ff4186 318
ansond 0:137634ff4186 319 int ctr_drbg_random_with_add( void *p_rng,
ansond 0:137634ff4186 320 unsigned char *output, size_t output_len,
ansond 0:137634ff4186 321 const unsigned char *additional, size_t add_len )
ansond 0:137634ff4186 322 {
ansond 0:137634ff4186 323 int ret = 0;
ansond 0:137634ff4186 324 ctr_drbg_context *ctx = (ctr_drbg_context *) p_rng;
ansond 0:137634ff4186 325 unsigned char add_input[CTR_DRBG_SEEDLEN];
ansond 0:137634ff4186 326 unsigned char *p = output;
ansond 0:137634ff4186 327 unsigned char tmp[CTR_DRBG_BLOCKSIZE];
ansond 0:137634ff4186 328 int i;
ansond 0:137634ff4186 329 size_t use_len;
ansond 0:137634ff4186 330
ansond 0:137634ff4186 331 if( output_len > CTR_DRBG_MAX_REQUEST )
ansond 0:137634ff4186 332 return( POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG );
ansond 0:137634ff4186 333
ansond 0:137634ff4186 334 if( add_len > CTR_DRBG_MAX_INPUT )
ansond 0:137634ff4186 335 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
ansond 0:137634ff4186 336
ansond 0:137634ff4186 337 memset( add_input, 0, CTR_DRBG_SEEDLEN );
ansond 0:137634ff4186 338
ansond 0:137634ff4186 339 if( ctx->reseed_counter > ctx->reseed_interval ||
ansond 0:137634ff4186 340 ctx->prediction_resistance )
ansond 0:137634ff4186 341 {
ansond 0:137634ff4186 342 if( ( ret = ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
ansond 0:137634ff4186 343 return( ret );
ansond 0:137634ff4186 344
ansond 0:137634ff4186 345 add_len = 0;
ansond 0:137634ff4186 346 }
ansond 0:137634ff4186 347
ansond 0:137634ff4186 348 if( add_len > 0 )
ansond 0:137634ff4186 349 {
ansond 0:137634ff4186 350 block_cipher_df( add_input, additional, add_len );
ansond 0:137634ff4186 351 ctr_drbg_update_internal( ctx, add_input );
ansond 0:137634ff4186 352 }
ansond 0:137634ff4186 353
ansond 0:137634ff4186 354 while( output_len > 0 )
ansond 0:137634ff4186 355 {
ansond 0:137634ff4186 356 /*
ansond 0:137634ff4186 357 * Increase counter
ansond 0:137634ff4186 358 */
ansond 0:137634ff4186 359 for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
ansond 0:137634ff4186 360 if( ++ctx->counter[i - 1] != 0 )
ansond 0:137634ff4186 361 break;
ansond 0:137634ff4186 362
ansond 0:137634ff4186 363 /*
ansond 0:137634ff4186 364 * Crypt counter block
ansond 0:137634ff4186 365 */
ansond 0:137634ff4186 366 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, tmp );
ansond 0:137634ff4186 367
ansond 0:137634ff4186 368 use_len = ( output_len > CTR_DRBG_BLOCKSIZE ) ? CTR_DRBG_BLOCKSIZE :
ansond 0:137634ff4186 369 output_len;
ansond 0:137634ff4186 370 /*
ansond 0:137634ff4186 371 * Copy random block to destination
ansond 0:137634ff4186 372 */
ansond 0:137634ff4186 373 memcpy( p, tmp, use_len );
ansond 0:137634ff4186 374 p += use_len;
ansond 0:137634ff4186 375 output_len -= use_len;
ansond 0:137634ff4186 376 }
ansond 0:137634ff4186 377
ansond 0:137634ff4186 378 ctr_drbg_update_internal( ctx, add_input );
ansond 0:137634ff4186 379
ansond 0:137634ff4186 380 ctx->reseed_counter++;
ansond 0:137634ff4186 381
ansond 0:137634ff4186 382 return( 0 );
ansond 0:137634ff4186 383 }
ansond 0:137634ff4186 384
ansond 0:137634ff4186 385 int ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
ansond 0:137634ff4186 386 {
ansond 0:137634ff4186 387 return ctr_drbg_random_with_add( p_rng, output, output_len, NULL, 0 );
ansond 0:137634ff4186 388 }
ansond 0:137634ff4186 389
ansond 0:137634ff4186 390 #if defined(POLARSSL_FS_IO)
ansond 0:137634ff4186 391 int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path )
ansond 0:137634ff4186 392 {
ansond 0:137634ff4186 393 int ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR;
ansond 0:137634ff4186 394 FILE *f;
ansond 0:137634ff4186 395 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
ansond 0:137634ff4186 396
ansond 0:137634ff4186 397 if( ( f = fopen( path, "wb" ) ) == NULL )
ansond 0:137634ff4186 398 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
ansond 0:137634ff4186 399
ansond 0:137634ff4186 400 if( ( ret = ctr_drbg_random( ctx, buf, CTR_DRBG_MAX_INPUT ) ) != 0 )
ansond 0:137634ff4186 401 goto exit;
ansond 0:137634ff4186 402
ansond 0:137634ff4186 403 if( fwrite( buf, 1, CTR_DRBG_MAX_INPUT, f ) != CTR_DRBG_MAX_INPUT )
ansond 0:137634ff4186 404 {
ansond 0:137634ff4186 405 ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR;
ansond 0:137634ff4186 406 goto exit;
ansond 0:137634ff4186 407 }
ansond 0:137634ff4186 408
ansond 0:137634ff4186 409 ret = 0;
ansond 0:137634ff4186 410
ansond 0:137634ff4186 411 exit:
ansond 0:137634ff4186 412 fclose( f );
ansond 0:137634ff4186 413 return( ret );
ansond 0:137634ff4186 414 }
ansond 0:137634ff4186 415
ansond 0:137634ff4186 416 int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path )
ansond 0:137634ff4186 417 {
ansond 0:137634ff4186 418 FILE *f;
ansond 0:137634ff4186 419 size_t n;
ansond 0:137634ff4186 420 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
ansond 0:137634ff4186 421
ansond 0:137634ff4186 422 if( ( f = fopen( path, "rb" ) ) == NULL )
ansond 0:137634ff4186 423 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
ansond 0:137634ff4186 424
ansond 0:137634ff4186 425 fseek( f, 0, SEEK_END );
ansond 0:137634ff4186 426 n = (size_t) ftell( f );
ansond 0:137634ff4186 427 fseek( f, 0, SEEK_SET );
ansond 0:137634ff4186 428
ansond 0:137634ff4186 429 if( n > CTR_DRBG_MAX_INPUT )
ansond 0:137634ff4186 430 {
ansond 0:137634ff4186 431 fclose( f );
ansond 0:137634ff4186 432 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
ansond 0:137634ff4186 433 }
ansond 0:137634ff4186 434
ansond 0:137634ff4186 435 if( fread( buf, 1, n, f ) != n )
ansond 0:137634ff4186 436 {
ansond 0:137634ff4186 437 fclose( f );
ansond 0:137634ff4186 438 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
ansond 0:137634ff4186 439 }
ansond 0:137634ff4186 440
ansond 0:137634ff4186 441 fclose( f );
ansond 0:137634ff4186 442
ansond 0:137634ff4186 443 ctr_drbg_update( ctx, buf, n );
ansond 0:137634ff4186 444
ansond 0:137634ff4186 445 return( ctr_drbg_write_seed_file( ctx, path ) );
ansond 0:137634ff4186 446 }
ansond 0:137634ff4186 447 #endif /* POLARSSL_FS_IO */
ansond 0:137634ff4186 448
ansond 0:137634ff4186 449 #if defined(POLARSSL_SELF_TEST)
ansond 0:137634ff4186 450
ansond 0:137634ff4186 451 static const unsigned char entropy_source_pr[96] =
ansond 0:137634ff4186 452 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
ansond 0:137634ff4186 453 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
ansond 0:137634ff4186 454 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
ansond 0:137634ff4186 455 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
ansond 0:137634ff4186 456 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
ansond 0:137634ff4186 457 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
ansond 0:137634ff4186 458 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
ansond 0:137634ff4186 459 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
ansond 0:137634ff4186 460 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
ansond 0:137634ff4186 461 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
ansond 0:137634ff4186 462 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
ansond 0:137634ff4186 463 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
ansond 0:137634ff4186 464
ansond 0:137634ff4186 465 static const unsigned char entropy_source_nopr[64] =
ansond 0:137634ff4186 466 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
ansond 0:137634ff4186 467 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
ansond 0:137634ff4186 468 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
ansond 0:137634ff4186 469 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
ansond 0:137634ff4186 470 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
ansond 0:137634ff4186 471 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
ansond 0:137634ff4186 472 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
ansond 0:137634ff4186 473 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
ansond 0:137634ff4186 474
ansond 0:137634ff4186 475 static const unsigned char nonce_pers_pr[16] =
ansond 0:137634ff4186 476 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
ansond 0:137634ff4186 477 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
ansond 0:137634ff4186 478
ansond 0:137634ff4186 479 static const unsigned char nonce_pers_nopr[16] =
ansond 0:137634ff4186 480 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
ansond 0:137634ff4186 481 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
ansond 0:137634ff4186 482
ansond 0:137634ff4186 483 static const unsigned char result_pr[16] =
ansond 0:137634ff4186 484 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
ansond 0:137634ff4186 485 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
ansond 0:137634ff4186 486
ansond 0:137634ff4186 487 static const unsigned char result_nopr[16] =
ansond 0:137634ff4186 488 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
ansond 0:137634ff4186 489 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
ansond 0:137634ff4186 490
ansond 0:137634ff4186 491 static size_t test_offset;
ansond 0:137634ff4186 492 static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
ansond 0:137634ff4186 493 size_t len )
ansond 0:137634ff4186 494 {
ansond 0:137634ff4186 495 const unsigned char *p = data;
ansond 0:137634ff4186 496 memcpy( buf, p + test_offset, len );
ansond 0:137634ff4186 497 test_offset += len;
ansond 0:137634ff4186 498 return( 0 );
ansond 0:137634ff4186 499 }
ansond 0:137634ff4186 500
ansond 0:137634ff4186 501 #define CHK( c ) if( (c) != 0 ) \
ansond 0:137634ff4186 502 { \
ansond 0:137634ff4186 503 if( verbose != 0 ) \
ansond 0:137634ff4186 504 polarssl_printf( "failed\n" ); \
ansond 0:137634ff4186 505 return( 1 ); \
ansond 0:137634ff4186 506 }
ansond 0:137634ff4186 507
ansond 0:137634ff4186 508 /*
ansond 0:137634ff4186 509 * Checkup routine
ansond 0:137634ff4186 510 */
ansond 0:137634ff4186 511 int ctr_drbg_self_test( int verbose )
ansond 0:137634ff4186 512 {
ansond 0:137634ff4186 513 ctr_drbg_context ctx;
ansond 0:137634ff4186 514 unsigned char buf[16];
ansond 0:137634ff4186 515
ansond 0:137634ff4186 516 /*
ansond 0:137634ff4186 517 * Based on a NIST CTR_DRBG test vector (PR = True)
ansond 0:137634ff4186 518 */
ansond 0:137634ff4186 519 if( verbose != 0 )
ansond 0:137634ff4186 520 polarssl_printf( " CTR_DRBG (PR = TRUE) : " );
ansond 0:137634ff4186 521
ansond 0:137634ff4186 522 test_offset = 0;
ansond 0:137634ff4186 523 CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
ansond 0:137634ff4186 524 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
ansond 0:137634ff4186 525 ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON );
ansond 0:137634ff4186 526 CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) );
ansond 0:137634ff4186 527 CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) );
ansond 0:137634ff4186 528 CHK( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) );
ansond 0:137634ff4186 529
ansond 0:137634ff4186 530 if( verbose != 0 )
ansond 0:137634ff4186 531 polarssl_printf( "passed\n" );
ansond 0:137634ff4186 532
ansond 0:137634ff4186 533 /*
ansond 0:137634ff4186 534 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
ansond 0:137634ff4186 535 */
ansond 0:137634ff4186 536 if( verbose != 0 )
ansond 0:137634ff4186 537 polarssl_printf( " CTR_DRBG (PR = FALSE): " );
ansond 0:137634ff4186 538
ansond 0:137634ff4186 539 test_offset = 0;
ansond 0:137634ff4186 540 CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
ansond 0:137634ff4186 541 (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
ansond 0:137634ff4186 542 CHK( ctr_drbg_random( &ctx, buf, 16 ) );
ansond 0:137634ff4186 543 CHK( ctr_drbg_reseed( &ctx, NULL, 0 ) );
ansond 0:137634ff4186 544 CHK( ctr_drbg_random( &ctx, buf, 16 ) );
ansond 0:137634ff4186 545 CHK( memcmp( buf, result_nopr, 16 ) );
ansond 0:137634ff4186 546
ansond 0:137634ff4186 547 if( verbose != 0 )
ansond 0:137634ff4186 548 polarssl_printf( "passed\n" );
ansond 0:137634ff4186 549
ansond 0:137634ff4186 550 if( verbose != 0 )
ansond 0:137634ff4186 551 polarssl_printf( "\n" );
ansond 0:137634ff4186 552
ansond 0:137634ff4186 553 return( 0 );
ansond 0:137634ff4186 554 }
ansond 0:137634ff4186 555 #endif /* POLARSSL_SELF_TEST */
ansond 0:137634ff4186 556
ansond 0:137634ff4186 557 #endif /* POLARSSL_CTR_DRBG_C */
ansond 0:137634ff4186 558