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