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