Rtos API example

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ctr_drbg.c Source File

ctr_drbg.c

00001 /*
00002  *  CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
00003  *
00004  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
00005  *  SPDX-License-Identifier: Apache-2.0
00006  *
00007  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
00008  *  not use this file except in compliance with the License.
00009  *  You may obtain a copy of the License at
00010  *
00011  *  http://www.apache.org/licenses/LICENSE-2.0
00012  *
00013  *  Unless required by applicable law or agreed to in writing, software
00014  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00015  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00016  *  See the License for the specific language governing permissions and
00017  *  limitations under the License.
00018  *
00019  *  This file is part of mbed TLS (https://tls.mbed.org)
00020  */
00021 /*
00022  *  The NIST SP 800-90 DRBGs are described in the following publucation.
00023  *
00024  *  http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
00025  */
00026 
00027 #if !defined(MBEDTLS_CONFIG_FILE)
00028 #include "mbedtls/config.h"
00029 #else
00030 #include MBEDTLS_CONFIG_FILE
00031 #endif
00032 
00033 #if defined(MBEDTLS_CTR_DRBG_C)
00034 
00035 #include "mbedtls/ctr_drbg.h"
00036 
00037 #include <string.h>
00038 
00039 #if defined(MBEDTLS_FS_IO)
00040 #include <stdio.h>
00041 #endif
00042 
00043 #if defined(MBEDTLS_SELF_TEST)
00044 #if defined(MBEDTLS_PLATFORM_C)
00045 #include "mbedtls/platform.h"
00046 #else
00047 #include <stdio.h>
00048 #define mbedtls_printf printf
00049 #endif /* MBEDTLS_PLATFORM_C */
00050 #endif /* MBEDTLS_SELF_TEST */
00051 
00052 /* Implementation that should never be optimized out by the compiler */
00053 static void mbedtls_zeroize( void *v, size_t n ) {
00054     volatile unsigned char *p = v; while( n-- ) *p++ = 0;
00055 }
00056 
00057 /*
00058  * CTR_DRBG context initialization
00059  */
00060 void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
00061 {
00062     memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
00063 
00064 #if defined(MBEDTLS_THREADING_C)
00065     mbedtls_mutex_init( &ctx->mutex );
00066 #endif
00067 }
00068 
00069 /*
00070  * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow
00071  * NIST tests to succeed (which require known length fixed entropy)
00072  */
00073 int mbedtls_ctr_drbg_seed_entropy_len(
00074                    mbedtls_ctr_drbg_context *ctx,
00075                    int (*f_entropy)(void *, unsigned char *, size_t),
00076                    void *p_entropy,
00077                    const unsigned char *custom,
00078                    size_t len,
00079                    size_t entropy_len )
00080 {
00081     int ret;
00082     unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
00083 
00084     memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
00085 
00086     mbedtls_aes_init( &ctx->aes_ctx  );
00087 
00088     ctx->f_entropy = f_entropy;
00089     ctx->p_entropy  = p_entropy;
00090 
00091     ctx->entropy_len  = entropy_len;
00092     ctx->reseed_interval  = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
00093 
00094     /*
00095      * Initialize with an empty key
00096      */
00097     mbedtls_aes_setkey_enc( &ctx->aes_ctx , key, MBEDTLS_CTR_DRBG_KEYBITS );
00098 
00099     if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
00100         return( ret );
00101 
00102     return( 0 );
00103 }
00104 
00105 int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
00106                    int (*f_entropy)(void *, unsigned char *, size_t),
00107                    void *p_entropy,
00108                    const unsigned char *custom,
00109                    size_t len )
00110 {
00111     return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy, custom, len,
00112                                        MBEDTLS_CTR_DRBG_ENTROPY_LEN ) );
00113 }
00114 
00115 void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
00116 {
00117     if( ctx == NULL )
00118         return;
00119 
00120 #if defined(MBEDTLS_THREADING_C)
00121     mbedtls_mutex_free( &ctx->mutex );
00122 #endif
00123     mbedtls_aes_free( &ctx->aes_ctx  );
00124     mbedtls_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
00125 }
00126 
00127 void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
00128 {
00129     ctx->prediction_resistance  = resistance;
00130 }
00131 
00132 void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len )
00133 {
00134     ctx->entropy_len  = len;
00135 }
00136 
00137 void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval )
00138 {
00139     ctx->reseed_interval  = interval;
00140 }
00141 
00142 static int block_cipher_df( unsigned char *output,
00143                             const unsigned char *data, size_t data_len )
00144 {
00145     unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
00146     unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
00147     unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
00148     unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
00149     unsigned char *p, *iv;
00150     mbedtls_aes_context aes_ctx;
00151 
00152     int i, j;
00153     size_t buf_len, use_len;
00154 
00155     if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
00156         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
00157 
00158     memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
00159     mbedtls_aes_init( &aes_ctx );
00160 
00161     /*
00162      * Construct IV (16 bytes) and S in buffer
00163      * IV = Counter (in 32-bits) padded to 16 with zeroes
00164      * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
00165      *     data || 0x80
00166      *     (Total is padded to a multiple of 16-bytes with zeroes)
00167      */
00168     p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
00169     *p++ = ( data_len >> 24 ) & 0xff;
00170     *p++ = ( data_len >> 16 ) & 0xff;
00171     *p++ = ( data_len >> 8  ) & 0xff;
00172     *p++ = ( data_len       ) & 0xff;
00173     p += 3;
00174     *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
00175     memcpy( p, data, data_len );
00176     p[data_len] = 0x80;
00177 
00178     buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
00179 
00180     for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
00181         key[i] = i;
00182 
00183     mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS );
00184 
00185     /*
00186      * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
00187      */
00188     for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
00189     {
00190         p = buf;
00191         memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
00192         use_len = buf_len;
00193 
00194         while( use_len > 0 )
00195         {
00196             for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
00197                 chain[i] ^= p[i];
00198             p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
00199             use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
00200                        MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
00201 
00202             mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain );
00203         }
00204 
00205         memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
00206 
00207         /*
00208          * Update IV
00209          */
00210         buf[3]++;
00211     }
00212 
00213     /*
00214      * Do final encryption with reduced data
00215      */
00216     mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS );
00217     iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
00218     p = output;
00219 
00220     for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
00221     {
00222         mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
00223         memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
00224         p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
00225     }
00226 
00227     mbedtls_aes_free( &aes_ctx );
00228 
00229     return( 0 );
00230 }
00231 
00232 static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
00233                               const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
00234 {
00235     unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
00236     unsigned char *p = tmp;
00237     int i, j;
00238 
00239     memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
00240 
00241     for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
00242     {
00243         /*
00244          * Increase counter
00245          */
00246         for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
00247             if( ++ctx->counter [i - 1] != 0 )
00248                 break;
00249 
00250         /*
00251          * Crypt counter block
00252          */
00253         mbedtls_aes_crypt_ecb( &ctx->aes_ctx , MBEDTLS_AES_ENCRYPT, ctx->counter , p );
00254 
00255         p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
00256     }
00257 
00258     for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
00259         tmp[i] ^= data[i];
00260 
00261     /*
00262      * Update key and counter
00263      */
00264     mbedtls_aes_setkey_enc( &ctx->aes_ctx , tmp, MBEDTLS_CTR_DRBG_KEYBITS );
00265     memcpy( ctx->counter , tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
00266 
00267     return( 0 );
00268 }
00269 
00270 void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
00271                       const unsigned char *additional, size_t add_len )
00272 {
00273     unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
00274 
00275     if( add_len > 0 )
00276     {
00277         /* MAX_INPUT would be more logical here, but we have to match
00278          * block_cipher_df()'s limits since we can't propagate errors */
00279         if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
00280             add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
00281 
00282         block_cipher_df( add_input, additional, add_len );
00283         ctr_drbg_update_internal( ctx, add_input );
00284     }
00285 }
00286 
00287 int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
00288                      const unsigned char *additional, size_t len )
00289 {
00290     unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
00291     size_t seedlen = 0;
00292 
00293     if( ctx->entropy_len  > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
00294         len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len  )
00295         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
00296 
00297     memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
00298 
00299     /*
00300      * Gather entropy_len bytes of entropy to seed state
00301      */
00302     if( 0 != ctx->f_entropy( ctx->p_entropy , seed,
00303                              ctx->entropy_len  ) )
00304     {
00305         return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
00306     }
00307 
00308     seedlen += ctx->entropy_len ;
00309 
00310     /*
00311      * Add additional data
00312      */
00313     if( additional && len )
00314     {
00315         memcpy( seed + seedlen, additional, len );
00316         seedlen += len;
00317     }
00318 
00319     /*
00320      * Reduce to 384 bits
00321      */
00322     block_cipher_df( seed, seed, seedlen );
00323 
00324     /*
00325      * Update state
00326      */
00327     ctr_drbg_update_internal( ctx, seed );
00328     ctx->reseed_counter  = 1;
00329 
00330     return( 0 );
00331 }
00332 
00333 int mbedtls_ctr_drbg_random_with_add( void *p_rng,
00334                               unsigned char *output, size_t output_len,
00335                               const unsigned char *additional, size_t add_len )
00336 {
00337     int ret = 0;
00338     mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
00339     unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
00340     unsigned char *p = output;
00341     unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
00342     int i;
00343     size_t use_len;
00344 
00345     if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
00346         return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
00347 
00348     if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
00349         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
00350 
00351     memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
00352 
00353     if( ctx->reseed_counter  > ctx->reseed_interval  ||
00354         ctx->prediction_resistance  )
00355     {
00356         if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
00357             return( ret );
00358 
00359         add_len = 0;
00360     }
00361 
00362     if( add_len > 0 )
00363     {
00364         block_cipher_df( add_input, additional, add_len );
00365         ctr_drbg_update_internal( ctx, add_input );
00366     }
00367 
00368     while( output_len > 0 )
00369     {
00370         /*
00371          * Increase counter
00372          */
00373         for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
00374             if( ++ctx->counter [i - 1] != 0 )
00375                 break;
00376 
00377         /*
00378          * Crypt counter block
00379          */
00380         mbedtls_aes_crypt_ecb( &ctx->aes_ctx , MBEDTLS_AES_ENCRYPT, ctx->counter , tmp );
00381 
00382         use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
00383                                                        output_len;
00384         /*
00385          * Copy random block to destination
00386          */
00387         memcpy( p, tmp, use_len );
00388         p += use_len;
00389         output_len -= use_len;
00390     }
00391 
00392     ctr_drbg_update_internal( ctx, add_input );
00393 
00394     ctx->reseed_counter ++;
00395 
00396     return( 0 );
00397 }
00398 
00399 int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
00400 {
00401     int ret;
00402     mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
00403 
00404 #if defined(MBEDTLS_THREADING_C)
00405     if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
00406         return( ret );
00407 #endif
00408 
00409     ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
00410 
00411 #if defined(MBEDTLS_THREADING_C)
00412     if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
00413         return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
00414 #endif
00415 
00416     return( ret );
00417 }
00418 
00419 #if defined(MBEDTLS_FS_IO)
00420 int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
00421 {
00422     int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
00423     FILE *f;
00424     unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
00425 
00426     if( ( f = fopen( path, "wb" ) ) == NULL )
00427         return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
00428 
00429     if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
00430         goto exit;
00431 
00432     if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
00433     {
00434         ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
00435         goto exit;
00436     }
00437 
00438     ret = 0;
00439 
00440 exit:
00441     fclose( f );
00442     return( ret );
00443 }
00444 
00445 int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
00446 {
00447     FILE *f;
00448     size_t n;
00449     unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
00450 
00451     if( ( f = fopen( path, "rb" ) ) == NULL )
00452         return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
00453 
00454     fseek( f, 0, SEEK_END );
00455     n = (size_t) ftell( f );
00456     fseek( f, 0, SEEK_SET );
00457 
00458     if( n > MBEDTLS_CTR_DRBG_MAX_INPUT )
00459     {
00460         fclose( f );
00461         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
00462     }
00463 
00464     if( fread( buf, 1, n, f ) != n )
00465     {
00466         fclose( f );
00467         return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
00468     }
00469 
00470     fclose( f );
00471 
00472     mbedtls_ctr_drbg_update( ctx, buf, n );
00473 
00474     return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
00475 }
00476 #endif /* MBEDTLS_FS_IO */
00477 
00478 #if defined(MBEDTLS_SELF_TEST)
00479 
00480 static const unsigned char entropy_source_pr[96] =
00481     { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
00482       0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
00483       0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
00484       0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
00485       0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
00486       0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
00487       0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
00488       0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
00489       0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
00490       0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
00491       0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
00492       0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
00493 
00494 static const unsigned char entropy_source_nopr[64] =
00495     { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
00496       0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
00497       0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
00498       0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
00499       0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
00500       0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
00501       0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
00502       0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
00503 
00504 static const unsigned char nonce_pers_pr[16] =
00505     { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
00506       0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
00507 
00508 static const unsigned char nonce_pers_nopr[16] =
00509     { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
00510       0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
00511 
00512 static const unsigned char result_pr[16] =
00513     { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
00514       0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
00515 
00516 static const unsigned char result_nopr[16] =
00517     { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
00518       0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
00519 
00520 static size_t test_offset;
00521 static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
00522                                        size_t len )
00523 {
00524     const unsigned char *p = data;
00525     memcpy( buf, p + test_offset, len );
00526     test_offset += len;
00527     return( 0 );
00528 }
00529 
00530 #define CHK( c )    if( (c) != 0 )                          \
00531                     {                                       \
00532                         if( verbose != 0 )                  \
00533                             mbedtls_printf( "failed\n" );  \
00534                         return( 1 );                        \
00535                     }
00536 
00537 /*
00538  * Checkup routine
00539  */
00540 int mbedtls_ctr_drbg_self_test( int verbose )
00541 {
00542     mbedtls_ctr_drbg_context ctx;
00543     unsigned char buf[16];
00544 
00545     mbedtls_ctr_drbg_init( &ctx );
00546 
00547     /*
00548      * Based on a NIST CTR_DRBG test vector (PR = True)
00549      */
00550     if( verbose != 0 )
00551         mbedtls_printf( "  CTR_DRBG (PR = TRUE) : " );
00552 
00553     test_offset = 0;
00554     CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
00555                                 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
00556     mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
00557     CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
00558     CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
00559     CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
00560 
00561     mbedtls_ctr_drbg_free( &ctx );
00562 
00563     if( verbose != 0 )
00564         mbedtls_printf( "passed\n" );
00565 
00566     /*
00567      * Based on a NIST CTR_DRBG test vector (PR = FALSE)
00568      */
00569     if( verbose != 0 )
00570         mbedtls_printf( "  CTR_DRBG (PR = FALSE): " );
00571 
00572     mbedtls_ctr_drbg_init( &ctx );
00573 
00574     test_offset = 0;
00575     CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
00576                             (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
00577     CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
00578     CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
00579     CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
00580     CHK( memcmp( buf, result_nopr, 16 ) );
00581 
00582     mbedtls_ctr_drbg_free( &ctx );
00583 
00584     if( verbose != 0 )
00585         mbedtls_printf( "passed\n" );
00586 
00587     if( verbose != 0 )
00588             mbedtls_printf( "\n" );
00589 
00590     return( 0 );
00591 }
00592 #endif /* MBEDTLS_SELF_TEST */
00593 
00594 #endif /* MBEDTLS_CTR_DRBG_C */