blob: d3888483a36b4266249bf2934aafc218e1ae85b4 [file] [log] [blame]
Paul Bakker0e04d0e2011-11-27 14:46:59 +00001/*
2 * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakker0e04d0e2011-11-27 14:46:59 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000020 */
21/*
22 * The NIST SP 800-90 DRBGs are described in the following publucation.
23 *
24 * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
25 */
26
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020027#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000028#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020029#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020030#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020031#endif
Paul Bakker0e04d0e2011-11-27 14:46:59 +000032
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020033#if defined(MBEDTLS_CTR_DRBG_C)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000034
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000035#include "mbedtls/ctr_drbg.h"
Paul Bakker0e04d0e2011-11-27 14:46:59 +000036
Rich Evans00ab4702015-02-06 13:43:58 +000037#include <string.h>
38
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020039#if defined(MBEDTLS_FS_IO)
Paul Bakkerfc754a92011-12-05 13:23:51 +000040#include <stdio.h>
41#endif
42
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020043#if defined(MBEDTLS_SELF_TEST)
44#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000045#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010046#else
Rich Evans00ab4702015-02-06 13:43:58 +000047#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020048#define mbedtls_printf printf
49#endif /* MBEDTLS_PLATFORM_C */
50#endif /* MBEDTLS_SELF_TEST */
Paul Bakker7dc4c442014-02-01 22:50:26 +010051
Paul Bakkerfff03662014-06-18 16:21:25 +020052/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020053static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakkerfff03662014-06-18 16:21:25 +020054 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
55}
56
Paul Bakker18d32912011-12-10 21:42:49 +000057/*
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020058 * CTR_DRBG context initialization
59 */
60void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
61{
62 memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010063
64#if defined(MBEDTLS_THREADING_C)
65 mbedtls_mutex_init( &ctx->mutex );
66#endif
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020067}
68
69/*
Paul Bakker18d32912011-12-10 21:42:49 +000070 * Non-public function wrapped by ctr_crbg_init(). Necessary to allow NIST
71 * tests to succeed (which require known length fixed entropy)
72 */
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020073int mbedtls_ctr_drbg_seed_entropy_len(
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020074 mbedtls_ctr_drbg_context *ctx,
Paul Bakker0e04d0e2011-11-27 14:46:59 +000075 int (*f_entropy)(void *, unsigned char *, size_t),
76 void *p_entropy,
Paul Bakker1bc9efc2011-12-03 11:29:32 +000077 const unsigned char *custom,
Paul Bakker18d32912011-12-10 21:42:49 +000078 size_t len,
79 size_t entropy_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000080{
81 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020082 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Paul Bakker0e04d0e2011-11-27 14:46:59 +000083
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020084 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000085
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020086 mbedtls_aes_init( &ctx->aes_ctx );
Paul Bakkerc7ea99a2014-06-18 11:12:03 +020087
Paul Bakker0e04d0e2011-11-27 14:46:59 +000088 ctx->f_entropy = f_entropy;
89 ctx->p_entropy = p_entropy;
90
Paul Bakker18d32912011-12-10 21:42:49 +000091 ctx->entropy_len = entropy_len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020092 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
Paul Bakker0e04d0e2011-11-27 14:46:59 +000093
94 /*
95 * Initialize with an empty key
96 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020097 mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000098
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020099 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000100 return( ret );
101
102 return( 0 );
103}
104
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200105int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker18d32912011-12-10 21:42:49 +0000106 int (*f_entropy)(void *, unsigned char *, size_t),
107 void *p_entropy,
108 const unsigned char *custom,
109 size_t len )
110{
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200111 return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy, custom, len,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200112 MBEDTLS_CTR_DRBG_ENTROPY_LEN ) );
Paul Bakker18d32912011-12-10 21:42:49 +0000113}
114
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200115void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
Paul Bakkerfff03662014-06-18 16:21:25 +0200116{
117 if( ctx == NULL )
118 return;
119
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100120#if defined(MBEDTLS_THREADING_C)
121 mbedtls_mutex_free( &ctx->mutex );
122#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200123 mbedtls_aes_free( &ctx->aes_ctx );
124 mbedtls_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Paul Bakkerfff03662014-06-18 16:21:25 +0200125}
126
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200127void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000128{
129 ctx->prediction_resistance = resistance;
130}
131
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200132void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000133{
134 ctx->entropy_len = len;
135}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200136
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200137void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000138{
139 ctx->reseed_interval = interval;
140}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200141
142static int block_cipher_df( unsigned char *output,
143 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000144{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200145 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
146 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
147 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
148 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100149 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200150 mbedtls_aes_context aes_ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000151
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200152 int i, j;
153 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000154
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200155 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
156 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100157
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200158 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
159 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000160
161 /*
162 * Construct IV (16 bytes) and S in buffer
163 * IV = Counter (in 32-bits) padded to 16 with zeroes
164 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
165 * data || 0x80
166 * (Total is padded to a multiple of 16-bytes with zeroes)
167 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200168 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000169 *p++ = ( data_len >> 24 ) & 0xff;
170 *p++ = ( data_len >> 16 ) & 0xff;
171 *p++ = ( data_len >> 8 ) & 0xff;
172 *p++ = ( data_len ) & 0xff;
173 p += 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200174 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000175 memcpy( p, data, data_len );
176 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000177
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200178 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000179
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200180 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000181 key[i] = i;
182
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200183 mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000184
185 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200186 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000187 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200188 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000189 {
190 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200191 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000192 use_len = buf_len;
193
194 while( use_len > 0 )
195 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200196 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000197 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200198 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
199 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
200 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000201
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200202 mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000203 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200204
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200205 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000206
207 /*
208 * Update IV
209 */
210 buf[3]++;
211 }
212
213 /*
214 * Do final encryption with reduced data
215 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200216 mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS );
217 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000218 p = output;
219
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200220 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000221 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200222 mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
223 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
224 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000225 }
226
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200227 mbedtls_aes_free( &aes_ctx );
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200228
Gilles Peskine43c19642018-11-27 16:37:23 +0100229 mbedtls_zeroize( buf, sizeof( buf ) );
230 mbedtls_zeroize( tmp, sizeof( tmp ) );
231 mbedtls_zeroize( key, sizeof( key ) );
232 mbedtls_zeroize( chain, sizeof( chain ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000233 return( 0 );
234}
235
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200236static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
237 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000238{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200239 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000240 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000241 int i, j;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000242
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200243 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000244
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200245 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000246 {
247 /*
248 * Increase counter
249 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200250 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000251 if( ++ctx->counter[i - 1] != 0 )
252 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000253
254 /*
255 * Crypt counter block
256 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200257 mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000258
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200259 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000260 }
261
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200262 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000263 tmp[i] ^= data[i];
264
265 /*
266 * Update key and counter
267 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200268 mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS );
269 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000270
Gilles Peskine17b2ac22018-09-11 15:34:17 +0200271 mbedtls_zeroize( tmp, sizeof( tmp ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000272 return( 0 );
273}
274
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200275void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000276 const unsigned char *additional, size_t add_len )
277{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200278 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000279
280 if( add_len > 0 )
281 {
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100282 /* MAX_INPUT would be more logical here, but we have to match
283 * block_cipher_df()'s limits since we can't propagate errors */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200284 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
285 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100286
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000287 block_cipher_df( add_input, additional, add_len );
288 ctr_drbg_update_internal( ctx, add_input );
Gilles Peskine17b2ac22018-09-11 15:34:17 +0200289 mbedtls_zeroize( add_input, sizeof( add_input ) );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000290 }
291}
292
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200293int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000294 const unsigned char *additional, size_t len )
295{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200296 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000297 size_t seedlen = 0;
298
Andres Amaya Garciaef1329e2017-01-17 23:24:02 +0000299 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
300 len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200301 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000302
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200303 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000304
305 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200306 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000307 */
308 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
309 ctx->entropy_len ) )
310 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200311 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000312 }
313
314 seedlen += ctx->entropy_len;
315
316 /*
317 * Add additional data
318 */
319 if( additional && len )
320 {
321 memcpy( seed + seedlen, additional, len );
322 seedlen += len;
323 }
324
325 /*
326 * Reduce to 384 bits
327 */
328 block_cipher_df( seed, seed, seedlen );
329
330 /*
331 * Update state
332 */
333 ctr_drbg_update_internal( ctx, seed );
334 ctx->reseed_counter = 1;
335
Gilles Peskine17b2ac22018-09-11 15:34:17 +0200336 mbedtls_zeroize( seed, sizeof( seed ) );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000337 return( 0 );
338}
Paul Bakker9af723c2014-05-01 13:03:14 +0200339
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200340int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000341 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000342 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000343{
344 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200345 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
346 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000347 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200348 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000349 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000350 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000351
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200352 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
353 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000354
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200355 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
356 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000357
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200358 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000359
360 if( ctx->reseed_counter > ctx->reseed_interval ||
361 ctx->prediction_resistance )
362 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200363 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000364 return( ret );
365
366 add_len = 0;
367 }
368
369 if( add_len > 0 )
370 {
371 block_cipher_df( add_input, additional, add_len );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000372 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000373 }
374
375 while( output_len > 0 )
376 {
377 /*
378 * Increase counter
379 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200380 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000381 if( ++ctx->counter[i - 1] != 0 )
382 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000383
384 /*
385 * Crypt counter block
386 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200387 mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000388
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200389 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200390 output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000391 /*
392 * Copy random block to destination
393 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000394 memcpy( p, tmp, use_len );
395 p += use_len;
396 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000397 }
398
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000399 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000400
401 ctx->reseed_counter++;
402
Gilles Peskine17b2ac22018-09-11 15:34:17 +0200403 mbedtls_zeroize( add_input, sizeof( add_input ) );
404 mbedtls_zeroize( tmp, sizeof( tmp ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000405 return( 0 );
406}
407
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200408int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000409{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100410 int ret;
411 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
412
413#if defined(MBEDTLS_THREADING_C)
414 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
415 return( ret );
416#endif
417
418 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
419
420#if defined(MBEDTLS_THREADING_C)
421 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
422 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
423#endif
424
425 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000426}
427
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200428#if defined(MBEDTLS_FS_IO)
429int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000430{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200431 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000432 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200433 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000434
435 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200436 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000437
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200438 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200439 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000440
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200441 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200442 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Andres Amaya Garciae0a727e2017-06-26 10:56:58 +0100443 else
444 ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000445
Andres Amaya Garciac17cc442017-06-27 16:57:26 +0100446exit:
Andres Amaya Garciae0a727e2017-06-26 10:56:58 +0100447 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200448
Paul Bakkerfc754a92011-12-05 13:23:51 +0000449 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200450 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000451}
452
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200453int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000454{
Andres Amaya Garciae0a727e2017-06-26 10:56:58 +0100455 int ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000456 FILE *f;
457 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200458 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000459
460 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200461 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000462
463 fseek( f, 0, SEEK_END );
464 n = (size_t) ftell( f );
465 fseek( f, 0, SEEK_SET );
466
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200467 if( n > MBEDTLS_CTR_DRBG_MAX_INPUT )
Andres Amaya Garciac17cc442017-06-27 16:57:26 +0100468 {
469 fclose( f );
470 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
471 }
472
473 if( fread( buf, 1, n, f ) != n )
Andres Amaya Garciae0a727e2017-06-26 10:56:58 +0100474 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
475 else
476 mbedtls_ctr_drbg_update( ctx, buf, n );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000477
Paul Bakkerfc754a92011-12-05 13:23:51 +0000478 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200479
Andres Amaya Garciae0a727e2017-06-26 10:56:58 +0100480 mbedtls_zeroize( buf, sizeof( buf ) );
481
482 if( ret != 0 )
483 return( ret );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200484
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200485 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000486}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200487#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000488
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200489#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000490
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000491static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000492 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
493 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
494 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
495 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
496 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
497 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
498 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
499 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
500 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
501 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
502 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
503 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
504
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000505static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000506 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
507 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
508 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
509 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
510 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
511 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
512 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
513 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
514
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100515static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000516 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
517 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
518
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100519static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000520 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
521 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
522
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100523static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000524 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
525 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
526
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100527static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000528 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
529 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
530
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100531static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200532static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
533 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000534{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100535 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000536 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100537 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000538 return( 0 );
539}
540
Paul Bakker7dc4c442014-02-01 22:50:26 +0100541#define CHK( c ) if( (c) != 0 ) \
542 { \
543 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200544 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100545 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100546 }
547
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000548/*
549 * Checkup routine
550 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200551int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000552{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200553 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000554 unsigned char buf[16];
555
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200556 mbedtls_ctr_drbg_init( &ctx );
557
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000558 /*
559 * Based on a NIST CTR_DRBG test vector (PR = True)
560 */
561 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200562 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000563
564 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200565 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000566 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200567 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
568 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
569 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
570 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000571
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100572 mbedtls_ctr_drbg_free( &ctx );
573
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000574 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200575 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000576
577 /*
578 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
579 */
580 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200581 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000582
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100583 mbedtls_ctr_drbg_init( &ctx );
584
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000585 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200586 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000587 (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200588 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
589 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
590 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100591 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000592
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100593 mbedtls_ctr_drbg_free( &ctx );
594
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000595 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200596 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000597
598 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200599 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000600
601 return( 0 );
602}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200603#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000604
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200605#endif /* MBEDTLS_CTR_DRBG_C */