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