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