Knight KE / Mbed OS Game_Master
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 publication.
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 #include "mbedtls/platform_util.h"
00037 
00038 #include <string.h>
00039 
00040 #if defined(MBEDTLS_FS_IO)
00041 #include <stdio.h>
00042 #endif
00043 
00044 #if defined(MBEDTLS_SELF_TEST)
00045 #if defined(MBEDTLS_PLATFORM_C)
00046 #include "mbedtls/platform.h"
00047 #else
00048 #include <stdio.h>
00049 #define mbedtls_printf printf
00050 #endif /* MBEDTLS_PLATFORM_C */
00051 #endif /* MBEDTLS_SELF_TEST */
00052 
00053 /*
00054  * CTR_DRBG context initialization
00055  */
00056 void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
00057 {
00058     memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
00059 
00060 #if defined(MBEDTLS_THREADING_C)
00061     mbedtls_mutex_init( &ctx->mutex );
00062 #endif
00063 }
00064 
00065 /*
00066  * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow
00067  * NIST tests to succeed (which require known length fixed entropy)
00068  */
00069 int mbedtls_ctr_drbg_seed_entropy_len(
00070                    mbedtls_ctr_drbg_context *ctx,
00071                    int (*f_entropy)(void *, unsigned char *, size_t),
00072                    void *p_entropy,
00073                    const unsigned char *custom,
00074                    size_t len,
00075                    size_t entropy_len )
00076 {
00077     int ret;
00078     unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
00079 
00080     memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
00081 
00082     mbedtls_aes_init( &ctx->aes_ctx  );
00083 
00084     ctx->f_entropy  = f_entropy;
00085     ctx->p_entropy  = p_entropy;
00086 
00087     ctx->entropy_len  = entropy_len;
00088     ctx->reseed_interval  = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
00089 
00090     /*
00091      * Initialize with an empty key
00092      */
00093     if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx , key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
00094     {
00095         return( ret );
00096     }
00097 
00098     if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
00099     {
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_platform_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     int ret = 0;
00152 
00153     int i, j;
00154     size_t buf_len, use_len;
00155 
00156     if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
00157         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
00158 
00159     memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
00160     mbedtls_aes_init( &aes_ctx );
00161 
00162     /*
00163      * Construct IV (16 bytes) and S in buffer
00164      * IV = Counter (in 32-bits) padded to 16 with zeroes
00165      * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
00166      *     data || 0x80
00167      *     (Total is padded to a multiple of 16-bytes with zeroes)
00168      */
00169     p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
00170     *p++ = ( data_len >> 24 ) & 0xff;
00171     *p++ = ( data_len >> 16 ) & 0xff;
00172     *p++ = ( data_len >> 8  ) & 0xff;
00173     *p++ = ( data_len       ) & 0xff;
00174     p += 3;
00175     *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
00176     memcpy( p, data, data_len );
00177     p[data_len] = 0x80;
00178 
00179     buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
00180 
00181     for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
00182         key[i] = i;
00183 
00184     if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
00185     {
00186         goto exit;
00187     }
00188 
00189     /*
00190      * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
00191      */
00192     for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
00193     {
00194         p = buf;
00195         memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
00196         use_len = buf_len;
00197 
00198         while( use_len > 0 )
00199         {
00200             for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
00201                 chain[i] ^= p[i];
00202             p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
00203             use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
00204                        MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
00205 
00206             if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ) ) != 0 )
00207             {
00208                 goto exit;
00209             }
00210         }
00211 
00212         memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
00213 
00214         /*
00215          * Update IV
00216          */
00217         buf[3]++;
00218     }
00219 
00220     /*
00221      * Do final encryption with reduced data
00222      */
00223     if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
00224     {
00225         goto exit;
00226     }
00227     iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
00228     p = output;
00229 
00230     for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
00231     {
00232         if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) ) != 0 )
00233         {
00234             goto exit;
00235         }
00236         memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
00237         p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
00238     }
00239 exit:
00240     mbedtls_aes_free( &aes_ctx );
00241     /*
00242     * tidy up the stack
00243     */
00244     mbedtls_platform_zeroize( buf, sizeof( buf ) );
00245     mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
00246     mbedtls_platform_zeroize( key, sizeof( key ) );
00247     mbedtls_platform_zeroize( chain, sizeof( chain ) );
00248     if( 0 != ret )
00249     {
00250         /*
00251         * wipe partial seed from memory
00252         */
00253         mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
00254     }
00255 
00256     return( ret );
00257 }
00258 
00259 static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
00260                               const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
00261 {
00262     unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
00263     unsigned char *p = tmp;
00264     int i, j;
00265     int ret = 0;
00266 
00267     memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
00268 
00269     for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
00270     {
00271         /*
00272          * Increase counter
00273          */
00274         for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
00275             if( ++ctx->counter [i - 1] != 0 )
00276                 break;
00277 
00278         /*
00279          * Crypt counter block
00280          */
00281         if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx , MBEDTLS_AES_ENCRYPT, ctx->counter , p ) ) != 0 )
00282         {
00283             return( ret );
00284         }
00285 
00286         p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
00287     }
00288 
00289     for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
00290         tmp[i] ^= data[i];
00291 
00292     /*
00293      * Update key and counter
00294      */
00295     if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx , tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
00296     {
00297         return( ret );
00298     }
00299     memcpy( ctx->counter , tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
00300 
00301     return( 0 );
00302 }
00303 
00304 void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
00305                       const unsigned char *additional, size_t add_len )
00306 {
00307     unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
00308 
00309     if( add_len > 0 )
00310     {
00311         /* MAX_INPUT would be more logical here, but we have to match
00312          * block_cipher_df()'s limits since we can't propagate errors */
00313         if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
00314             add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
00315 
00316         block_cipher_df( add_input, additional, add_len );
00317         ctr_drbg_update_internal( ctx, add_input );
00318     }
00319 }
00320 
00321 int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
00322                      const unsigned char *additional, size_t len )
00323 {
00324     unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
00325     size_t seedlen = 0;
00326     int ret;
00327 
00328     if( ctx->entropy_len  > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
00329         len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len  )
00330         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
00331 
00332     memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
00333 
00334     /*
00335      * Gather entropy_len bytes of entropy to seed state
00336      */
00337     if( 0 != ctx->f_entropy ( ctx->p_entropy , seed,
00338                              ctx->entropy_len  ) )
00339     {
00340         return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
00341     }
00342 
00343     seedlen += ctx->entropy_len ;
00344 
00345     /*
00346      * Add additional data
00347      */
00348     if( additional && len )
00349     {
00350         memcpy( seed + seedlen, additional, len );
00351         seedlen += len;
00352     }
00353 
00354     /*
00355      * Reduce to 384 bits
00356      */
00357     if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
00358     {
00359         return( ret );
00360     }
00361 
00362     /*
00363      * Update state
00364      */
00365     if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
00366     {
00367         return( ret );
00368     }
00369     ctx->reseed_counter  = 1;
00370 
00371     return( 0 );
00372 }
00373 
00374 int mbedtls_ctr_drbg_random_with_add( void *p_rng,
00375                               unsigned char *output, size_t output_len,
00376                               const unsigned char *additional, size_t add_len )
00377 {
00378     int ret = 0;
00379     mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
00380     unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
00381     unsigned char *p = output;
00382     unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
00383     int i;
00384     size_t use_len;
00385 
00386     if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
00387         return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
00388 
00389     if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
00390         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
00391 
00392     memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
00393 
00394     if( ctx->reseed_counter  > ctx->reseed_interval  ||
00395         ctx->prediction_resistance  )
00396     {
00397         if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
00398         {
00399             return( ret );
00400         }
00401         add_len = 0;
00402     }
00403 
00404     if( add_len > 0 )
00405     {
00406         if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
00407         {
00408             return( ret );
00409         }
00410         if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
00411         {
00412             return( ret );
00413         }
00414     }
00415 
00416     while( output_len > 0 )
00417     {
00418         /*
00419          * Increase counter
00420          */
00421         for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
00422             if( ++ctx->counter [i - 1] != 0 )
00423                 break;
00424 
00425         /*
00426          * Crypt counter block
00427          */
00428         if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx , MBEDTLS_AES_ENCRYPT, ctx->counter , tmp ) ) != 0 )
00429         {
00430             return( ret );
00431         }
00432 
00433         use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
00434                                                        output_len;
00435         /*
00436          * Copy random block to destination
00437          */
00438         memcpy( p, tmp, use_len );
00439         p += use_len;
00440         output_len -= use_len;
00441     }
00442 
00443     if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
00444     {
00445         return( ret );
00446     }
00447 
00448     ctx->reseed_counter ++;
00449 
00450     return( 0 );
00451 }
00452 
00453 int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
00454 {
00455     int ret;
00456     mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
00457 
00458 #if defined(MBEDTLS_THREADING_C)
00459     if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
00460         return( ret );
00461 #endif
00462 
00463     ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
00464 
00465 #if defined(MBEDTLS_THREADING_C)
00466     if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
00467         return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
00468 #endif
00469 
00470     return( ret );
00471 }
00472 
00473 #if defined(MBEDTLS_FS_IO)
00474 int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
00475 {
00476     int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
00477     FILE *f;
00478     unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
00479 
00480     if( ( f = fopen( path, "wb" ) ) == NULL )
00481         return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
00482 
00483     if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
00484         goto exit;
00485 
00486     if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
00487         ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
00488     else
00489         ret = 0;
00490 
00491 exit:
00492     mbedtls_platform_zeroize( buf, sizeof( buf ) );
00493 
00494     fclose( f );
00495     return( ret );
00496 }
00497 
00498 int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
00499 {
00500     int ret = 0;
00501     FILE *f;
00502     size_t n;
00503     unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
00504 
00505     if( ( f = fopen( path, "rb" ) ) == NULL )
00506         return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
00507 
00508     fseek( f, 0, SEEK_END );
00509     n = (size_t) ftell( f );
00510     fseek( f, 0, SEEK_SET );
00511 
00512     if( n > MBEDTLS_CTR_DRBG_MAX_INPUT )
00513     {
00514         fclose( f );
00515         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
00516     }
00517 
00518     if( fread( buf, 1, n, f ) != n )
00519         ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
00520     else
00521         mbedtls_ctr_drbg_update( ctx, buf, n );
00522 
00523     fclose( f );
00524 
00525     mbedtls_platform_zeroize( buf, sizeof( buf ) );
00526 
00527     if( ret != 0 )
00528         return( ret );
00529 
00530     return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
00531 }
00532 #endif /* MBEDTLS_FS_IO */
00533 
00534 #if defined(MBEDTLS_SELF_TEST)
00535 
00536 static const unsigned char entropy_source_pr[96] =
00537     { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
00538       0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
00539       0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
00540       0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
00541       0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
00542       0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
00543       0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
00544       0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
00545       0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
00546       0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
00547       0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
00548       0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
00549 
00550 static const unsigned char entropy_source_nopr[64] =
00551     { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
00552       0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
00553       0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
00554       0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
00555       0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
00556       0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
00557       0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
00558       0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
00559 
00560 static const unsigned char nonce_pers_pr[16] =
00561     { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
00562       0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
00563 
00564 static const unsigned char nonce_pers_nopr[16] =
00565     { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
00566       0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
00567 
00568 static const unsigned char result_pr[16] =
00569     { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
00570       0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
00571 
00572 static const unsigned char result_nopr[16] =
00573     { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
00574       0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
00575 
00576 static size_t test_offset;
00577 static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
00578                                        size_t len )
00579 {
00580     const unsigned char *p = data;
00581     memcpy( buf, p + test_offset, len );
00582     test_offset += len;
00583     return( 0 );
00584 }
00585 
00586 #define CHK( c )    if( (c) != 0 )                          \
00587                     {                                       \
00588                         if( verbose != 0 )                  \
00589                             mbedtls_printf( "failed\n" );  \
00590                         return( 1 );                        \
00591                     }
00592 
00593 /*
00594  * Checkup routine
00595  */
00596 int mbedtls_ctr_drbg_self_test( int verbose )
00597 {
00598     mbedtls_ctr_drbg_context ctx;
00599     unsigned char buf[16];
00600 
00601     mbedtls_ctr_drbg_init( &ctx );
00602 
00603     /*
00604      * Based on a NIST CTR_DRBG test vector (PR = True)
00605      */
00606     if( verbose != 0 )
00607         mbedtls_printf( "  CTR_DRBG (PR = TRUE) : " );
00608 
00609     test_offset = 0;
00610     CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
00611                                 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
00612     mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
00613     CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
00614     CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
00615     CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
00616 
00617     mbedtls_ctr_drbg_free( &ctx );
00618 
00619     if( verbose != 0 )
00620         mbedtls_printf( "passed\n" );
00621 
00622     /*
00623      * Based on a NIST CTR_DRBG test vector (PR = FALSE)
00624      */
00625     if( verbose != 0 )
00626         mbedtls_printf( "  CTR_DRBG (PR = FALSE): " );
00627 
00628     mbedtls_ctr_drbg_init( &ctx );
00629 
00630     test_offset = 0;
00631     CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
00632                             (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
00633     CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
00634     CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
00635     CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
00636     CHK( memcmp( buf, result_nopr, 16 ) );
00637 
00638     mbedtls_ctr_drbg_free( &ctx );
00639 
00640     if( verbose != 0 )
00641         mbedtls_printf( "passed\n" );
00642 
00643     if( verbose != 0 )
00644             mbedtls_printf( "\n" );
00645 
00646     return( 0 );
00647 }
00648 #endif /* MBEDTLS_SELF_TEST */
00649 
00650 #endif /* MBEDTLS_CTR_DRBG_C */