00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "polarssl/config.h"
00032
00033 #if defined(POLARSSL_CTR_DRBG_C)
00034
00035 #include "polarssl/ctr_drbg.h"
00036
00037 #if defined(POLARSSL_FS_IO)
00038 #include <stdio.h>
00039 #endif
00040
00041
00042
00043
00044
00045 int ctr_drbg_init_entropy_len(
00046 ctr_drbg_context *ctx,
00047 int (*f_entropy)(void *, unsigned char *, size_t),
00048 void *p_entropy,
00049 const unsigned char *custom,
00050 size_t len,
00051 size_t entropy_len )
00052 {
00053 int ret;
00054 unsigned char key[CTR_DRBG_KEYSIZE];
00055
00056 memset( ctx, 0, sizeof(ctr_drbg_context) );
00057 memset( key, 0, CTR_DRBG_KEYSIZE );
00058
00059 ctx->f_entropy = f_entropy;
00060 ctx->p_entropy = p_entropy;
00061
00062 ctx->entropy_len = entropy_len;
00063 ctx->reseed_interval = CTR_DRBG_RESEED_INTERVAL;
00064
00065
00066
00067
00068 aes_setkey_enc( &ctx->aes_ctx, key, CTR_DRBG_KEYBITS );
00069
00070 if( ( ret = ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
00071 return( ret );
00072
00073 return( 0 );
00074 }
00075
00076 int ctr_drbg_init( ctr_drbg_context *ctx,
00077 int (*f_entropy)(void *, unsigned char *, size_t),
00078 void *p_entropy,
00079 const unsigned char *custom,
00080 size_t len )
00081 {
00082 return( ctr_drbg_init_entropy_len( ctx, f_entropy, p_entropy, custom, len,
00083 CTR_DRBG_ENTROPY_LEN ) );
00084 }
00085
00086 void ctr_drbg_set_prediction_resistance( ctr_drbg_context *ctx, int resistance )
00087 {
00088 ctx->prediction_resistance = resistance;
00089 }
00090
00091 void ctr_drbg_set_entropy_len( ctr_drbg_context *ctx, size_t len )
00092 {
00093 ctx->entropy_len = len;
00094 }
00095
00096 void ctr_drbg_set_reseed_interval( ctr_drbg_context *ctx, int interval )
00097 {
00098 ctx->reseed_interval = interval;
00099 }
00100
00101 static int block_cipher_df( unsigned char *output,
00102 const unsigned char *data, size_t data_len )
00103 {
00104 unsigned char buf[CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16];
00105 unsigned char tmp[CTR_DRBG_SEEDLEN];
00106 unsigned char key[CTR_DRBG_KEYSIZE];
00107 unsigned char chain[CTR_DRBG_BLOCKSIZE];
00108 unsigned char *p = buf, *iv;
00109 aes_context aes_ctx;
00110
00111 int i, j;
00112 size_t buf_len, use_len;
00113
00114 memset( buf, 0, CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16 );
00115
00116
00117
00118
00119
00120
00121
00122
00123 p = buf + CTR_DRBG_BLOCKSIZE;
00124 *p++ = ( data_len >> 24 ) & 0xff;
00125 *p++ = ( data_len >> 16 ) & 0xff;
00126 *p++ = ( data_len >> 8 ) & 0xff;
00127 *p++ = ( data_len ) & 0xff;
00128 p += 3;
00129 *p++ = CTR_DRBG_SEEDLEN;
00130 memcpy( p, data, data_len );
00131 p[data_len] = 0x80;
00132
00133 buf_len = CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
00134
00135 for( i = 0; i < CTR_DRBG_KEYSIZE; i++ )
00136 key[i] = i;
00137
00138 aes_setkey_enc( &aes_ctx, key, CTR_DRBG_KEYBITS );
00139
00140
00141
00142
00143 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
00144 {
00145 p = buf;
00146 memset( chain, 0, CTR_DRBG_BLOCKSIZE );
00147 use_len = buf_len;
00148
00149 while( use_len > 0 )
00150 {
00151 for( i = 0; i < CTR_DRBG_BLOCKSIZE; i++ )
00152 chain[i] ^= p[i];
00153 p += CTR_DRBG_BLOCKSIZE;
00154 use_len -= ( use_len >= CTR_DRBG_BLOCKSIZE ) ?
00155 CTR_DRBG_BLOCKSIZE : use_len;
00156
00157 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, chain, chain );
00158 }
00159
00160 memcpy( tmp + j, chain, CTR_DRBG_BLOCKSIZE );
00161
00162
00163
00164
00165 buf[3]++;
00166 }
00167
00168
00169
00170
00171 aes_setkey_enc( &aes_ctx, tmp, CTR_DRBG_KEYBITS );
00172 iv = tmp + CTR_DRBG_KEYSIZE;
00173 p = output;
00174
00175 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
00176 {
00177 aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, iv, iv );
00178 memcpy( p, iv, CTR_DRBG_BLOCKSIZE );
00179 p += CTR_DRBG_BLOCKSIZE;
00180 }
00181
00182 return( 0 );
00183 }
00184
00185 static int ctr_drbg_update_internal( ctr_drbg_context *ctx,
00186 const unsigned char data[CTR_DRBG_SEEDLEN] )
00187 {
00188 unsigned char tmp[CTR_DRBG_SEEDLEN];
00189 unsigned char *p = tmp;
00190 int i, j;
00191
00192 memset( tmp, 0, CTR_DRBG_SEEDLEN );
00193
00194 for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
00195 {
00196
00197
00198
00199 for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
00200 if( ++ctx->counter[i - 1] != 0 )
00201 break;
00202
00203
00204
00205
00206 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, p );
00207
00208 p += CTR_DRBG_BLOCKSIZE;
00209 }
00210
00211 for( i = 0; i < CTR_DRBG_SEEDLEN; i++ )
00212 tmp[i] ^= data[i];
00213
00214
00215
00216
00217 aes_setkey_enc( &ctx->aes_ctx, tmp, CTR_DRBG_KEYBITS );
00218 memcpy( ctx->counter, tmp + CTR_DRBG_KEYSIZE, CTR_DRBG_BLOCKSIZE );
00219
00220 return( 0 );
00221 }
00222
00223 void ctr_drbg_update( ctr_drbg_context *ctx,
00224 const unsigned char *additional, size_t add_len )
00225 {
00226 unsigned char add_input[CTR_DRBG_SEEDLEN];
00227
00228 if( add_len > 0 )
00229 {
00230 block_cipher_df( add_input, additional, add_len );
00231 ctr_drbg_update_internal( ctx, add_input );
00232 }
00233 }
00234
00235 int ctr_drbg_reseed( ctr_drbg_context *ctx,
00236 const unsigned char *additional, size_t len )
00237 {
00238 unsigned char seed[CTR_DRBG_MAX_SEED_INPUT];
00239 size_t seedlen = 0;
00240
00241 if( ctx->entropy_len + len > CTR_DRBG_MAX_SEED_INPUT )
00242 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
00243
00244 memset( seed, 0, CTR_DRBG_MAX_SEED_INPUT );
00245
00246
00247
00248
00249 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
00250 ctx->entropy_len ) )
00251 {
00252 return( POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
00253 }
00254
00255 seedlen += ctx->entropy_len;
00256
00257
00258
00259
00260 if( additional && len )
00261 {
00262 memcpy( seed + seedlen, additional, len );
00263 seedlen += len;
00264 }
00265
00266
00267
00268
00269 block_cipher_df( seed, seed, seedlen );
00270
00271
00272
00273
00274 ctr_drbg_update_internal( ctx, seed );
00275 ctx->reseed_counter = 1;
00276
00277 return( 0 );
00278 }
00279
00280 int ctr_drbg_random_with_add( void *p_rng,
00281 unsigned char *output, size_t output_len,
00282 const unsigned char *additional, size_t add_len )
00283 {
00284 int ret = 0;
00285 ctr_drbg_context *ctx = (ctr_drbg_context *) p_rng;
00286 unsigned char add_input[CTR_DRBG_SEEDLEN];
00287 unsigned char *p = output;
00288 unsigned char tmp[CTR_DRBG_BLOCKSIZE];
00289 int i;
00290 size_t use_len;
00291
00292 if( output_len > CTR_DRBG_MAX_REQUEST )
00293 return( POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG );
00294
00295 if( add_len > CTR_DRBG_MAX_INPUT )
00296 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
00297
00298 memset( add_input, 0, CTR_DRBG_SEEDLEN );
00299
00300 if( ctx->reseed_counter > ctx->reseed_interval ||
00301 ctx->prediction_resistance )
00302 {
00303 if( ( ret = ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
00304 return( ret );
00305
00306 add_len = 0;
00307 }
00308
00309 if( add_len > 0 )
00310 {
00311 block_cipher_df( add_input, additional, add_len );
00312 ctr_drbg_update_internal( ctx, add_input );
00313 }
00314
00315 while( output_len > 0 )
00316 {
00317
00318
00319
00320 for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
00321 if( ++ctx->counter[i - 1] != 0 )
00322 break;
00323
00324
00325
00326
00327 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, tmp );
00328
00329 use_len = (output_len > CTR_DRBG_BLOCKSIZE ) ? CTR_DRBG_BLOCKSIZE : output_len;
00330
00331
00332
00333 memcpy( p, tmp, use_len );
00334 p += use_len;
00335 output_len -= use_len;
00336 }
00337
00338 ctr_drbg_update_internal( ctx, add_input );
00339
00340 ctx->reseed_counter++;
00341
00342 return( 0 );
00343 }
00344
00345 int ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
00346 {
00347 return ctr_drbg_random_with_add( p_rng, output, output_len, NULL, 0 );
00348 }
00349
00350 #if defined(POLARSSL_FS_IO)
00351 int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path )
00352 {
00353 int ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR;
00354 FILE *f;
00355 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
00356
00357 if( ( f = fopen( path, "wb" ) ) == NULL )
00358 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
00359
00360 if( ( ret = ctr_drbg_random( ctx, buf, CTR_DRBG_MAX_INPUT ) ) != 0 )
00361 goto exit;
00362
00363 if( fwrite( buf, 1, CTR_DRBG_MAX_INPUT, f ) != CTR_DRBG_MAX_INPUT )
00364 {
00365 ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR;
00366 goto exit;
00367 }
00368
00369 ret = 0;
00370
00371 exit:
00372 fclose( f );
00373 return( ret );
00374 }
00375
00376 int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path )
00377 {
00378 FILE *f;
00379 size_t n;
00380 unsigned char buf[ CTR_DRBG_MAX_INPUT ];
00381
00382 if( ( f = fopen( path, "rb" ) ) == NULL )
00383 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
00384
00385 fseek( f, 0, SEEK_END );
00386 n = (size_t) ftell( f );
00387 fseek( f, 0, SEEK_SET );
00388
00389 if( n > CTR_DRBG_MAX_INPUT )
00390 {
00391 fclose( f );
00392 return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
00393 }
00394
00395 if( fread( buf, 1, n, f ) != n )
00396 {
00397 fclose( f );
00398 return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
00399 }
00400
00401 fclose( f );
00402
00403 ctr_drbg_update( ctx, buf, n );
00404
00405 return( ctr_drbg_write_seed_file( ctx, path ) );
00406 }
00407 #endif
00408
00409 #if defined(POLARSSL_SELF_TEST)
00410
00411 #include <stdio.h>
00412
00413 unsigned char entropy_source_pr[96] =
00414 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
00415 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
00416 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
00417 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
00418 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
00419 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
00420 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
00421 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
00422 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
00423 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
00424 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
00425 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
00426
00427 unsigned char entropy_source_nopr[64] =
00428 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
00429 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
00430 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
00431 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
00432 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
00433 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
00434 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
00435 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
00436
00437 unsigned char nonce_pers_pr[16] =
00438 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
00439 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
00440
00441 unsigned char nonce_pers_nopr[16] =
00442 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
00443 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
00444
00445 unsigned char result_pr[16] =
00446 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
00447 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
00448
00449 unsigned char result_nopr[16] =
00450 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
00451 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
00452
00453 int test_offset;
00454 static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
00455 size_t len )
00456 {
00457 unsigned char *p = data;
00458 memcpy( buf, p + test_offset, len );
00459 test_offset += 32;
00460 return( 0 );
00461 }
00462
00463
00464
00465
00466 int ctr_drbg_self_test( int verbose )
00467 {
00468 ctr_drbg_context ctx;
00469 unsigned char buf[16];
00470
00471
00472
00473
00474 if( verbose != 0 )
00475 printf( " CTR_DRBG (PR = TRUE) : " );
00476
00477 test_offset = 0;
00478 if( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy, entropy_source_pr, nonce_pers_pr, 16, 32 ) != 0 )
00479 {
00480 if( verbose != 0 )
00481 printf( "failed\n" );
00482
00483 return( 1 );
00484 }
00485 ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON );
00486
00487 if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 )
00488 {
00489 if( verbose != 0 )
00490 printf( "failed\n" );
00491
00492 return( 1 );
00493 }
00494
00495 if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 )
00496 {
00497 if( verbose != 0 )
00498 printf( "failed\n" );
00499
00500 return( 1 );
00501 }
00502
00503 if( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) != 0 )
00504 {
00505 if( verbose != 0 )
00506 printf( "failed\n" );
00507
00508 return( 1 );
00509 }
00510
00511 if( verbose != 0 )
00512 printf( "passed\n" );
00513
00514
00515
00516
00517 if( verbose != 0 )
00518 printf( " CTR_DRBG (PR = FALSE): " );
00519
00520 test_offset = 0;
00521 if( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy, entropy_source_nopr, nonce_pers_nopr, 16, 32 ) != 0 )
00522 {
00523 if( verbose != 0 )
00524 printf( "failed\n" );
00525
00526 return( 1 );
00527 }
00528
00529 if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
00530 {
00531 if( verbose != 0 )
00532 printf( "failed\n" );
00533
00534 return( 1 );
00535 }
00536
00537 if( ctr_drbg_reseed( &ctx, NULL, 0 ) != 0 )
00538 {
00539 if( verbose != 0 )
00540 printf( "failed\n" );
00541
00542 return( 1 );
00543 }
00544
00545 if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
00546 {
00547 if( verbose != 0 )
00548 printf( "failed\n" );
00549
00550 return( 1 );
00551 }
00552
00553 if( memcmp( buf, result_nopr, 16 ) != 0 )
00554 {
00555 if( verbose != 0 )
00556 printf( "failed\n" );
00557
00558 return( 1 );
00559 }
00560
00561 if( verbose != 0 )
00562 printf( "passed\n" );
00563
00564 if( verbose != 0 )
00565 printf( "\n" );
00566
00567 return( 0 );
00568 }
00569 #endif
00570
00571 #endif