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