1 /*
2  *  CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
3  *
4  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5  *  SPDX-License-Identifier: Apache-2.0
6  *
7  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
8  *  not use this file except in compliance with the License.
9  *  You may obtain a copy of the License at
10  *
11  *  http://www.apache.org/licenses/LICENSE-2.0
12  *
13  *  Unless required by applicable law or agreed to in writing, software
14  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  *  See the License for the specific language governing permissions and
17  *  limitations under the License.
18  *
19  *  This file is part of mbed TLS (https://tls.mbed.org)
20  */
21 /*
22  *  The NIST SP 800-90 DRBGs are described in the following publucation.
23  *
24  *  http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
25  */
26 
27 #if !defined(MBEDTLS_CONFIG_FILE)
28 #include "mbedtls/config.h"
29 #else
30 #include MBEDTLS_CONFIG_FILE
31 #endif
32 
33 #if defined(MBEDTLS_CTR_DRBG_C)
34 
35 #include "mbedtls/ctr_drbg.h"
36 
37 #include <string.h>
38 
39 #if defined(MBEDTLS_FS_IO)
40 #include <stdio.h>
41 #endif
42 
43 #if defined(MBEDTLS_SELF_TEST)
44 #if defined(MBEDTLS_PLATFORM_C)
45 #include "mbedtls/platform.h"
46 #else
47 #include <stdio.h>
48 #define mbedtls_printf printf
49 #endif /* MBEDTLS_PLATFORM_C */
50 #endif /* MBEDTLS_SELF_TEST */
51 
52 /* Implementation that should never be optimized out by the compiler */
mbedtls_zeroize(void * v,size_t n)53 static void mbedtls_zeroize( void *v, size_t n ) {
54     volatile unsigned char *p = v; while( n-- ) *p++ = 0;
55 }
56 
57 /*
58  * CTR_DRBG context initialization
59  */
mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context * ctx)60 void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
61 {
62     memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
63 
64 #if defined(MBEDTLS_THREADING_C)
65     mbedtls_mutex_init( &ctx->mutex );
66 #endif
67 }
68 
69 /*
70  * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow
71  * NIST tests to succeed (which require known length fixed entropy)
72  */
mbedtls_ctr_drbg_seed_entropy_len(mbedtls_ctr_drbg_context * ctx,int (* f_entropy)(void *,unsigned char *,size_t),void * p_entropy,const unsigned char * custom,size_t len,size_t entropy_len)73 int mbedtls_ctr_drbg_seed_entropy_len(
74                    mbedtls_ctr_drbg_context *ctx,
75                    int (*f_entropy)(void *, unsigned char *, size_t),
76                    void *p_entropy,
77                    const unsigned char *custom,
78                    size_t len,
79                    size_t entropy_len )
80 {
81     int ret;
82     unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
83 
84     memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
85 
86     mbedtls_aes_init( &ctx->aes_ctx );
87 
88     ctx->f_entropy = f_entropy;
89     ctx->p_entropy = p_entropy;
90 
91     ctx->entropy_len = entropy_len;
92     ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
93 
94     /*
95      * Initialize with an empty key
96      */
97     mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS );
98 
99     if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
100         return( ret );
101 
102     return( 0 );
103 }
104 
mbedtls_ctr_drbg_seed(mbedtls_ctr_drbg_context * ctx,int (* f_entropy)(void *,unsigned char *,size_t),void * p_entropy,const unsigned char * custom,size_t len)105 int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
106                    int (*f_entropy)(void *, unsigned char *, size_t),
107                    void *p_entropy,
108                    const unsigned char *custom,
109                    size_t len )
110 {
111     return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy, custom, len,
112                                        MBEDTLS_CTR_DRBG_ENTROPY_LEN ) );
113 }
114 
mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context * ctx)115 void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
116 {
117     if( ctx == NULL )
118         return;
119 
120 #if defined(MBEDTLS_THREADING_C)
121     mbedtls_mutex_free( &ctx->mutex );
122 #endif
123     mbedtls_aes_free( &ctx->aes_ctx );
124     mbedtls_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
125 }
126 
mbedtls_ctr_drbg_set_prediction_resistance(mbedtls_ctr_drbg_context * ctx,int resistance)127 void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
128 {
129     ctx->prediction_resistance = resistance;
130 }
131 
mbedtls_ctr_drbg_set_entropy_len(mbedtls_ctr_drbg_context * ctx,size_t len)132 void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len )
133 {
134     ctx->entropy_len = len;
135 }
136 
mbedtls_ctr_drbg_set_reseed_interval(mbedtls_ctr_drbg_context * ctx,int interval)137 void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval )
138 {
139     ctx->reseed_interval = interval;
140 }
141 
block_cipher_df(unsigned char * output,const unsigned char * data,size_t data_len)142 static int block_cipher_df( unsigned char *output,
143                             const unsigned char *data, size_t data_len )
144 {
145     unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
146     unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
147     unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
148     unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
149     unsigned char *p, *iv;
150     mbedtls_aes_context aes_ctx;
151 
152     int i, j;
153     size_t buf_len, use_len;
154 
155     if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
156         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
157 
158     memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
159     mbedtls_aes_init( &aes_ctx );
160 
161     /*
162      * Construct IV (16 bytes) and S in buffer
163      * IV = Counter (in 32-bits) padded to 16 with zeroes
164      * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
165      *     data || 0x80
166      *     (Total is padded to a multiple of 16-bytes with zeroes)
167      */
168     p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
169     *p++ = ( data_len >> 24 ) & 0xff;
170     *p++ = ( data_len >> 16 ) & 0xff;
171     *p++ = ( data_len >> 8  ) & 0xff;
172     *p++ = ( data_len       ) & 0xff;
173     p += 3;
174     *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
175     memcpy( p, data, data_len );
176     p[data_len] = 0x80;
177 
178     buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
179 
180     for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
181         key[i] = i;
182 
183     mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS );
184 
185     /*
186      * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
187      */
188     for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
189     {
190         p = buf;
191         memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
192         use_len = buf_len;
193 
194         while( use_len > 0 )
195         {
196             for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
197                 chain[i] ^= p[i];
198             p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
199             use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
200                        MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
201 
202             mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain );
203         }
204 
205         memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
206 
207         /*
208          * Update IV
209          */
210         buf[3]++;
211     }
212 
213     /*
214      * Do final encryption with reduced data
215      */
216     mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS );
217     iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
218     p = output;
219 
220     for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
221     {
222         mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
223         memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
224         p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
225     }
226 
227     mbedtls_aes_free( &aes_ctx );
228 
229     return( 0 );
230 }
231 
ctr_drbg_update_internal(mbedtls_ctr_drbg_context * ctx,const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN])232 static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
233                               const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
234 {
235     unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
236     unsigned char *p = tmp;
237     int i, j;
238 
239     memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
240 
241     for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
242     {
243         /*
244          * Increase counter
245          */
246         for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
247             if( ++ctx->counter[i - 1] != 0 )
248                 break;
249 
250         /*
251          * Crypt counter block
252          */
253         mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p );
254 
255         p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
256     }
257 
258     for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
259         tmp[i] ^= data[i];
260 
261     /*
262      * Update key and counter
263      */
264     mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS );
265     memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
266 
267     return( 0 );
268 }
269 
mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context * ctx,const unsigned char * additional,size_t add_len)270 void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
271                       const unsigned char *additional, size_t add_len )
272 {
273     unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
274 
275     if( add_len > 0 )
276     {
277         /* MAX_INPUT would be more logical here, but we have to match
278          * block_cipher_df()'s limits since we can't propagate errors */
279         if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
280             add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
281 
282         block_cipher_df( add_input, additional, add_len );
283         ctr_drbg_update_internal( ctx, add_input );
284     }
285 }
286 
mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context * ctx,const unsigned char * additional,size_t len)287 int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
288                      const unsigned char *additional, size_t len )
289 {
290     unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
291     size_t seedlen = 0;
292 
293     if( ctx->entropy_len + len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
294         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
295 
296     memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
297 
298     /*
299      * Gather entropy_len bytes of entropy to seed state
300      */
301     if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
302                              ctx->entropy_len ) )
303     {
304         return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
305     }
306 
307     seedlen += ctx->entropy_len;
308 
309     /*
310      * Add additional data
311      */
312     if( additional && len )
313     {
314         memcpy( seed + seedlen, additional, len );
315         seedlen += len;
316     }
317 
318     /*
319      * Reduce to 384 bits
320      */
321     block_cipher_df( seed, seed, seedlen );
322 
323     /*
324      * Update state
325      */
326     ctr_drbg_update_internal( ctx, seed );
327     ctx->reseed_counter = 1;
328 
329     return( 0 );
330 }
331 
mbedtls_ctr_drbg_random_with_add(void * p_rng,unsigned char * output,size_t output_len,const unsigned char * additional,size_t add_len)332 int mbedtls_ctr_drbg_random_with_add( void *p_rng,
333                               unsigned char *output, size_t output_len,
334                               const unsigned char *additional, size_t add_len )
335 {
336     int ret = 0;
337     mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
338     unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
339     unsigned char *p = output;
340     unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
341     int i;
342     size_t use_len;
343 
344     if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
345         return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
346 
347     if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
348         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
349 
350     memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
351 
352     if( ctx->reseed_counter > ctx->reseed_interval ||
353         ctx->prediction_resistance )
354     {
355         if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
356             return( ret );
357 
358         add_len = 0;
359     }
360 
361     if( add_len > 0 )
362     {
363         block_cipher_df( add_input, additional, add_len );
364         ctr_drbg_update_internal( ctx, add_input );
365     }
366 
367     while( output_len > 0 )
368     {
369         /*
370          * Increase counter
371          */
372         for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
373             if( ++ctx->counter[i - 1] != 0 )
374                 break;
375 
376         /*
377          * Crypt counter block
378          */
379         mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp );
380 
381         use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
382                                                        output_len;
383         /*
384          * Copy random block to destination
385          */
386         memcpy( p, tmp, use_len );
387         p += use_len;
388         output_len -= use_len;
389     }
390 
391     ctr_drbg_update_internal( ctx, add_input );
392 
393     ctx->reseed_counter++;
394 
395     return( 0 );
396 }
397 
mbedtls_ctr_drbg_random(void * p_rng,unsigned char * output,size_t output_len)398 int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
399 {
400     int ret;
401     mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
402 
403 #if defined(MBEDTLS_THREADING_C)
404     if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
405         return( ret );
406 #endif
407 
408     ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
409 
410 #if defined(MBEDTLS_THREADING_C)
411     if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
412         return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
413 #endif
414 
415     return( ret );
416 }
417 
418 #if defined(MBEDTLS_FS_IO)
mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context * ctx,const char * path)419 int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
420 {
421     int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
422     FILE *f;
423     unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
424 
425     if( ( f = fopen( path, "wb" ) ) == NULL )
426         return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
427 
428     if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
429         goto exit;
430 
431     if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
432     {
433         ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
434         goto exit;
435     }
436 
437     ret = 0;
438 
439 exit:
440     fclose( f );
441     return( ret );
442 }
443 
mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context * ctx,const char * path)444 int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
445 {
446     FILE *f;
447     size_t n;
448     unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
449 
450     if( ( f = fopen( path, "rb" ) ) == NULL )
451         return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
452 
453     fseek( f, 0, SEEK_END );
454     n = (size_t) ftell( f );
455     fseek( f, 0, SEEK_SET );
456 
457     if( n > MBEDTLS_CTR_DRBG_MAX_INPUT )
458     {
459         fclose( f );
460         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
461     }
462 
463     if( fread( buf, 1, n, f ) != n )
464     {
465         fclose( f );
466         return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
467     }
468 
469     fclose( f );
470 
471     mbedtls_ctr_drbg_update( ctx, buf, n );
472 
473     return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
474 }
475 #endif /* MBEDTLS_FS_IO */
476 
477 #if defined(MBEDTLS_SELF_TEST)
478 
479 static const unsigned char entropy_source_pr[96] =
480     { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
481       0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
482       0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
483       0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
484       0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
485       0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
486       0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
487       0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
488       0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
489       0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
490       0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
491       0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
492 
493 static const unsigned char entropy_source_nopr[64] =
494     { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
495       0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
496       0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
497       0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
498       0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
499       0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
500       0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
501       0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
502 
503 static const unsigned char nonce_pers_pr[16] =
504     { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
505       0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
506 
507 static const unsigned char nonce_pers_nopr[16] =
508     { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
509       0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
510 
511 static const unsigned char result_pr[16] =
512     { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
513       0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
514 
515 static const unsigned char result_nopr[16] =
516     { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
517       0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
518 
519 static size_t test_offset;
ctr_drbg_self_test_entropy(void * data,unsigned char * buf,size_t len)520 static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
521                                        size_t len )
522 {
523     const unsigned char *p = data;
524     memcpy( buf, p + test_offset, len );
525     test_offset += len;
526     return( 0 );
527 }
528 
529 #define CHK( c )    if( (c) != 0 )                          \
530                     {                                       \
531                         if( verbose != 0 )                  \
532                             mbedtls_printf( "failed\n" );  \
533                         return( 1 );                        \
534                     }
535 
536 /*
537  * Checkup routine
538  */
mbedtls_ctr_drbg_self_test(int verbose)539 int mbedtls_ctr_drbg_self_test( int verbose )
540 {
541     mbedtls_ctr_drbg_context ctx;
542     unsigned char buf[16];
543 
544     mbedtls_ctr_drbg_init( &ctx );
545 
546     /*
547      * Based on a NIST CTR_DRBG test vector (PR = True)
548      */
549     if( verbose != 0 )
550         mbedtls_printf( "  CTR_DRBG (PR = TRUE) : " );
551 
552     test_offset = 0;
553     CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
554                                 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
555     mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
556     CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
557     CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
558     CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
559 
560     mbedtls_ctr_drbg_free( &ctx );
561 
562     if( verbose != 0 )
563         mbedtls_printf( "passed\n" );
564 
565     /*
566      * Based on a NIST CTR_DRBG test vector (PR = FALSE)
567      */
568     if( verbose != 0 )
569         mbedtls_printf( "  CTR_DRBG (PR = FALSE): " );
570 
571     mbedtls_ctr_drbg_init( &ctx );
572 
573     test_offset = 0;
574     CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
575                             (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
576     CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
577     CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
578     CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
579     CHK( memcmp( buf, result_nopr, 16 ) );
580 
581     mbedtls_ctr_drbg_free( &ctx );
582 
583     if( verbose != 0 )
584         mbedtls_printf( "passed\n" );
585 
586     if( verbose != 0 )
587             mbedtls_printf( "\n" );
588 
589     return( 0 );
590 }
591 #endif /* MBEDTLS_SELF_TEST */
592 
593 #endif /* MBEDTLS_CTR_DRBG_C */
594