xref: /reactos/dll/3rdparty/mbedtls/ctr_drbg.c (revision 01e5cb0c)
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         {
289             return( ret );
290         }
291 
292         p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
293     }
294 
295     for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
296         tmp[i] ^= data[i];
297 
298     /*
299      * Update key and counter
300      */
301     if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
302     {
303         return( ret );
304     }
305     memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
306 
307     return( 0 );
308 }
309 
310 void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
311                       const unsigned char *additional, size_t add_len )
312 {
313     unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
314 
315     if( add_len > 0 )
316     {
317         /* MAX_INPUT would be more logical here, but we have to match
318          * block_cipher_df()'s limits since we can't propagate errors */
319         if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
320             add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
321 
322         block_cipher_df( add_input, additional, add_len );
323         ctr_drbg_update_internal( ctx, add_input );
324     }
325 }
326 
327 int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
328                      const unsigned char *additional, size_t len )
329 {
330     unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
331     size_t seedlen = 0;
332     int ret;
333 
334     if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
335         len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
336         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
337 
338     memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
339 
340     /*
341      * Gather entropy_len bytes of entropy to seed state
342      */
343     if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
344                              ctx->entropy_len ) )
345     {
346         return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
347     }
348 
349     seedlen += ctx->entropy_len;
350 
351     /*
352      * Add additional data
353      */
354     if( additional && len )
355     {
356         memcpy( seed + seedlen, additional, len );
357         seedlen += len;
358     }
359 
360     /*
361      * Reduce to 384 bits
362      */
363     if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
364     {
365         return( ret );
366     }
367 
368     /*
369      * Update state
370      */
371     if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
372     {
373         return( ret );
374     }
375     ctx->reseed_counter = 1;
376 
377     return( 0 );
378 }
379 
380 int mbedtls_ctr_drbg_random_with_add( void *p_rng,
381                               unsigned char *output, size_t output_len,
382                               const unsigned char *additional, size_t add_len )
383 {
384     int ret = 0;
385     mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
386     unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
387     unsigned char *p = output;
388     unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
389     int i;
390     size_t use_len;
391 
392     if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
393         return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
394 
395     if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
396         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
397 
398     memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
399 
400     if( ctx->reseed_counter > ctx->reseed_interval ||
401         ctx->prediction_resistance )
402     {
403         if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
404         {
405             return( ret );
406         }
407         add_len = 0;
408     }
409 
410     if( add_len > 0 )
411     {
412         if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
413         {
414             return( ret );
415         }
416         if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
417         {
418             return( ret );
419         }
420     }
421 
422     while( output_len > 0 )
423     {
424         /*
425          * Increase counter
426          */
427         for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
428             if( ++ctx->counter[i - 1] != 0 )
429                 break;
430 
431         /*
432          * Crypt counter block
433          */
434         if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 )
435         {
436             return( ret );
437         }
438 
439         use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
440                                                        output_len;
441         /*
442          * Copy random block to destination
443          */
444         memcpy( p, tmp, use_len );
445         p += use_len;
446         output_len -= use_len;
447     }
448 
449     if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
450     {
451         return( ret );
452     }
453 
454     ctx->reseed_counter++;
455 
456     return( 0 );
457 }
458 
459 int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
460 {
461     int ret;
462     mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
463 
464 #if defined(MBEDTLS_THREADING_C)
465     if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
466         return( ret );
467 #endif
468 
469     ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
470 
471 #if defined(MBEDTLS_THREADING_C)
472     if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
473         return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
474 #endif
475 
476     return( ret );
477 }
478 
479 #if defined(MBEDTLS_FS_IO)
480 int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
481 {
482     int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
483     FILE *f;
484     unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
485 
486     if( ( f = fopen( path, "wb" ) ) == NULL )
487         return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
488 
489     if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
490         goto exit;
491 
492     if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
493         ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
494     else
495         ret = 0;
496 
497 exit:
498     mbedtls_zeroize( buf, sizeof( buf ) );
499 
500     fclose( f );
501     return( ret );
502 }
503 
504 int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
505 {
506     int ret = 0;
507     FILE *f;
508     size_t n;
509     unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
510 
511     if( ( f = fopen( path, "rb" ) ) == NULL )
512         return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
513 
514     fseek( f, 0, SEEK_END );
515     n = (size_t) ftell( f );
516     fseek( f, 0, SEEK_SET );
517 
518     if( n > MBEDTLS_CTR_DRBG_MAX_INPUT )
519     {
520         fclose( f );
521         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
522     }
523 
524     if( fread( buf, 1, n, f ) != n )
525         ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
526     else
527         mbedtls_ctr_drbg_update( ctx, buf, n );
528 
529     fclose( f );
530 
531     mbedtls_zeroize( buf, sizeof( buf ) );
532 
533     if( ret != 0 )
534         return( ret );
535 
536     return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
537 }
538 #endif /* MBEDTLS_FS_IO */
539 
540 #if defined(MBEDTLS_SELF_TEST)
541 
542 static const unsigned char entropy_source_pr[96] =
543     { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
544       0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
545       0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
546       0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
547       0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
548       0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
549       0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
550       0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
551       0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
552       0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
553       0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
554       0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
555 
556 static const unsigned char entropy_source_nopr[64] =
557     { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
558       0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
559       0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
560       0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
561       0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
562       0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
563       0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
564       0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
565 
566 static const unsigned char nonce_pers_pr[16] =
567     { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
568       0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
569 
570 static const unsigned char nonce_pers_nopr[16] =
571     { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
572       0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
573 
574 static const unsigned char result_pr[16] =
575     { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
576       0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
577 
578 static const unsigned char result_nopr[16] =
579     { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
580       0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
581 
582 static size_t test_offset;
583 static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
584                                        size_t len )
585 {
586     const unsigned char *p = data;
587     memcpy( buf, p + test_offset, len );
588     test_offset += len;
589     return( 0 );
590 }
591 
592 #define CHK( c )    if( (c) != 0 )                          \
593                     {                                       \
594                         if( verbose != 0 )                  \
595                             mbedtls_printf( "failed\n" );  \
596                         return( 1 );                        \
597                     }
598 
599 /*
600  * Checkup routine
601  */
602 int mbedtls_ctr_drbg_self_test( int verbose )
603 {
604     mbedtls_ctr_drbg_context ctx;
605     unsigned char buf[16];
606 
607     mbedtls_ctr_drbg_init( &ctx );
608 
609     /*
610      * Based on a NIST CTR_DRBG test vector (PR = True)
611      */
612     if( verbose != 0 )
613         mbedtls_printf( "  CTR_DRBG (PR = TRUE) : " );
614 
615     test_offset = 0;
616     CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
617                                 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
618     mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
619     CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
620     CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
621     CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
622 
623     mbedtls_ctr_drbg_free( &ctx );
624 
625     if( verbose != 0 )
626         mbedtls_printf( "passed\n" );
627 
628     /*
629      * Based on a NIST CTR_DRBG test vector (PR = FALSE)
630      */
631     if( verbose != 0 )
632         mbedtls_printf( "  CTR_DRBG (PR = FALSE): " );
633 
634     mbedtls_ctr_drbg_init( &ctx );
635 
636     test_offset = 0;
637     CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
638                             (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
639     CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
640     CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
641     CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
642     CHK( memcmp( buf, result_nopr, 16 ) );
643 
644     mbedtls_ctr_drbg_free( &ctx );
645 
646     if( verbose != 0 )
647         mbedtls_printf( "passed\n" );
648 
649     if( verbose != 0 )
650             mbedtls_printf( "\n" );
651 
652     return( 0 );
653 }
654 #endif /* MBEDTLS_SELF_TEST */
655 
656 #endif /* MBEDTLS_CTR_DRBG_C */
657