mbedtls ported to mbed-classic

Fork of mbedtls by Christopher Haster

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 ctr_crbg_init(). Necessary to allow NIST
00071  * 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  + len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
00294         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
00295 
00296     memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
00297 
00298     /*
00299      * Gather entropy_len bytes of entropy to seed state
00300      */
00301     if( 0 != ctx->f_entropy( ctx->p_entropy , seed,
00302                              ctx->entropy_len  ) )
00303     {
00304         return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
00305     }
00306 
00307     seedlen += ctx->entropy_len ;
00308 
00309     /*
00310      * Add additional data
00311      */
00312     if( additional && len )
00313     {
00314         memcpy( seed + seedlen, additional, len );
00315         seedlen += len;
00316     }
00317 
00318     /*
00319      * Reduce to 384 bits
00320      */
00321     block_cipher_df( seed, seed, seedlen );
00322 
00323     /*
00324      * Update state
00325      */
00326     ctr_drbg_update_internal( ctx, seed );
00327     ctx->reseed_counter  = 1;
00328 
00329     return( 0 );
00330 }
00331 
00332 int mbedtls_ctr_drbg_random_with_add( void *p_rng,
00333                               unsigned char *output, size_t output_len,
00334                               const unsigned char *additional, size_t add_len )
00335 {
00336     int ret = 0;
00337     mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
00338     unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
00339     unsigned char *p = output;
00340     unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
00341     int i;
00342     size_t use_len;
00343 
00344     if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
00345         return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
00346 
00347     if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
00348         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
00349 
00350     memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
00351 
00352     if( ctx->reseed_counter  > ctx->reseed_interval  ||
00353         ctx->prediction_resistance  )
00354     {
00355         if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
00356             return( ret );
00357 
00358         add_len = 0;
00359     }
00360 
00361     if( add_len > 0 )
00362     {
00363         block_cipher_df( add_input, additional, add_len );
00364         ctr_drbg_update_internal( ctx, add_input );
00365     }
00366 
00367     while( output_len > 0 )
00368     {
00369         /*
00370          * Increase counter
00371          */
00372         for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
00373             if( ++ctx->counter [i - 1] != 0 )
00374                 break;
00375 
00376         /*
00377          * Crypt counter block
00378          */
00379         mbedtls_aes_crypt_ecb( &ctx->aes_ctx , MBEDTLS_AES_ENCRYPT, ctx->counter , tmp );
00380 
00381         use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
00382                                                        output_len;
00383         /*
00384          * Copy random block to destination
00385          */
00386         memcpy( p, tmp, use_len );
00387         p += use_len;
00388         output_len -= use_len;
00389     }
00390 
00391     ctr_drbg_update_internal( ctx, add_input );
00392 
00393     ctx->reseed_counter ++;
00394 
00395     return( 0 );
00396 }
00397 
00398 int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
00399 {
00400     int ret;
00401     mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
00402 
00403 #if defined(MBEDTLS_THREADING_C)
00404     if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
00405         return( ret );
00406 #endif
00407 
00408     ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
00409 
00410 #if defined(MBEDTLS_THREADING_C)
00411     if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
00412         return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
00413 #endif
00414 
00415     return( ret );
00416 }
00417 
00418 #if defined(MBEDTLS_FS_IO)
00419 int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
00420 {
00421     int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
00422     FILE *f;
00423     unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
00424 
00425     if( ( f = fopen( path, "wb" ) ) == NULL )
00426         return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
00427 
00428     if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
00429         goto exit;
00430 
00431     if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
00432     {
00433         ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
00434         goto exit;
00435     }
00436 
00437     ret = 0;
00438 
00439 exit:
00440     fclose( f );
00441     return( ret );
00442 }
00443 
00444 int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
00445 {
00446     FILE *f;
00447     size_t n;
00448     unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
00449 
00450     if( ( f = fopen( path, "rb" ) ) == NULL )
00451         return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
00452 
00453     fseek( f, 0, SEEK_END );
00454     n = (size_t) ftell( f );
00455     fseek( f, 0, SEEK_SET );
00456 
00457     if( n > MBEDTLS_CTR_DRBG_MAX_INPUT )
00458     {
00459         fclose( f );
00460         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
00461     }
00462 
00463     if( fread( buf, 1, n, f ) != n )
00464     {
00465         fclose( f );
00466         return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
00467     }
00468 
00469     fclose( f );
00470 
00471     mbedtls_ctr_drbg_update( ctx, buf, n );
00472 
00473     return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
00474 }
00475 #endif /* MBEDTLS_FS_IO */
00476 
00477 #if defined(MBEDTLS_SELF_TEST)
00478 
00479 static const unsigned char entropy_source_pr[96] =
00480     { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
00481       0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
00482       0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
00483       0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
00484       0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
00485       0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
00486       0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
00487       0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
00488       0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
00489       0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
00490       0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
00491       0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
00492 
00493 static const unsigned char entropy_source_nopr[64] =
00494     { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
00495       0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
00496       0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
00497       0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
00498       0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
00499       0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
00500       0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
00501       0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
00502 
00503 static const unsigned char nonce_pers_pr[16] =
00504     { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
00505       0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
00506 
00507 static const unsigned char nonce_pers_nopr[16] =
00508     { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
00509       0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
00510 
00511 static const unsigned char result_pr[16] =
00512     { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
00513       0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
00514 
00515 static const unsigned char result_nopr[16] =
00516     { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
00517       0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
00518 
00519 static size_t test_offset;
00520 static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
00521                                        size_t len )
00522 {
00523     const unsigned char *p = data;
00524     memcpy( buf, p + test_offset, len );
00525     test_offset += len;
00526     return( 0 );
00527 }
00528 
00529 #define CHK( c )    if( (c) != 0 )                          \
00530                     {                                       \
00531                         if( verbose != 0 )                  \
00532                             mbedtls_printf( "failed\n" );  \
00533                         return( 1 );                        \
00534                     }
00535 
00536 /*
00537  * Checkup routine
00538  */
00539 int mbedtls_ctr_drbg_self_test( int verbose )
00540 {
00541     mbedtls_ctr_drbg_context ctx;
00542     unsigned char buf[16];
00543 
00544     mbedtls_ctr_drbg_init( &ctx );
00545 
00546     /*
00547      * Based on a NIST CTR_DRBG test vector (PR = True)
00548      */
00549     if( verbose != 0 )
00550         mbedtls_printf( "  CTR_DRBG (PR = TRUE) : " );
00551 
00552     test_offset = 0;
00553     CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
00554                                 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
00555     mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
00556     CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
00557     CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
00558     CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
00559 
00560     mbedtls_ctr_drbg_free( &ctx );
00561 
00562     if( verbose != 0 )
00563         mbedtls_printf( "passed\n" );
00564 
00565     /*
00566      * Based on a NIST CTR_DRBG test vector (PR = FALSE)
00567      */
00568     if( verbose != 0 )
00569         mbedtls_printf( "  CTR_DRBG (PR = FALSE): " );
00570 
00571     mbedtls_ctr_drbg_init( &ctx );
00572 
00573     test_offset = 0;
00574     CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
00575                             (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
00576     CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
00577     CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
00578     CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
00579     CHK( memcmp( buf, result_nopr, 16 ) );
00580 
00581     mbedtls_ctr_drbg_free( &ctx );
00582 
00583     if( verbose != 0 )
00584         mbedtls_printf( "passed\n" );
00585 
00586     if( verbose != 0 )
00587             mbedtls_printf( "\n" );
00588 
00589     return( 0 );
00590 }
00591 #endif /* MBEDTLS_SELF_TEST */
00592 
00593 #endif /* MBEDTLS_CTR_DRBG_C */