blob: c023c699e530b0cb57f1ea102711a2072c62342a [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
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000229 return( 0 );
230}
231
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200232static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
233 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000234{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200235 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000236 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000237 int i, j;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000238
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200239 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000240
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200241 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000242 {
243 /*
244 * Increase counter
245 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200246 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000247 if( ++ctx->counter[i - 1] != 0 )
248 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000249
250 /*
251 * Crypt counter block
252 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200253 mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000254
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200255 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000256 }
257
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200258 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000259 tmp[i] ^= data[i];
260
261 /*
262 * Update key and counter
263 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200264 mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS );
265 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000266
Gilles Peskine17b2ac22018-09-11 15:34:17 +0200267 mbedtls_zeroize( tmp, sizeof( tmp ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000268 return( 0 );
269}
270
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200271void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000272 const unsigned char *additional, size_t add_len )
273{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200274 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000275
276 if( add_len > 0 )
277 {
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100278 /* MAX_INPUT would be more logical here, but we have to match
279 * block_cipher_df()'s limits since we can't propagate errors */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200280 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
281 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100282
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000283 block_cipher_df( add_input, additional, add_len );
284 ctr_drbg_update_internal( ctx, add_input );
Gilles Peskine17b2ac22018-09-11 15:34:17 +0200285 mbedtls_zeroize( add_input, sizeof( add_input ) );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000286 }
287}
288
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200289int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000290 const unsigned char *additional, size_t len )
291{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200292 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000293 size_t seedlen = 0;
294
Andres Amaya Garciaef1329e2017-01-17 23:24:02 +0000295 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
296 len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200297 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000298
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200299 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000300
301 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200302 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000303 */
304 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
305 ctx->entropy_len ) )
306 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200307 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000308 }
309
310 seedlen += ctx->entropy_len;
311
312 /*
313 * Add additional data
314 */
315 if( additional && len )
316 {
317 memcpy( seed + seedlen, additional, len );
318 seedlen += len;
319 }
320
321 /*
322 * Reduce to 384 bits
323 */
324 block_cipher_df( seed, seed, seedlen );
325
326 /*
327 * Update state
328 */
329 ctr_drbg_update_internal( ctx, seed );
330 ctx->reseed_counter = 1;
331
Gilles Peskine17b2ac22018-09-11 15:34:17 +0200332 mbedtls_zeroize( seed, sizeof( seed ) );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000333 return( 0 );
334}
Paul Bakker9af723c2014-05-01 13:03:14 +0200335
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200336int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000337 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000338 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000339{
340 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200341 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
342 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000343 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200344 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000345 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000346 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000347
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200348 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
349 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000350
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200351 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
352 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000353
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200354 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000355
356 if( ctx->reseed_counter > ctx->reseed_interval ||
357 ctx->prediction_resistance )
358 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200359 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000360 return( ret );
361
362 add_len = 0;
363 }
364
365 if( add_len > 0 )
366 {
367 block_cipher_df( add_input, additional, add_len );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000368 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000369 }
370
371 while( output_len > 0 )
372 {
373 /*
374 * Increase counter
375 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200376 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000377 if( ++ctx->counter[i - 1] != 0 )
378 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000379
380 /*
381 * Crypt counter block
382 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200383 mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000384
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200385 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200386 output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000387 /*
388 * Copy random block to destination
389 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000390 memcpy( p, tmp, use_len );
391 p += use_len;
392 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000393 }
394
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000395 ctr_drbg_update_internal( ctx, add_input );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000396
397 ctx->reseed_counter++;
398
Gilles Peskine17b2ac22018-09-11 15:34:17 +0200399 mbedtls_zeroize( add_input, sizeof( add_input ) );
400 mbedtls_zeroize( tmp, sizeof( tmp ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000401 return( 0 );
402}
403
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200404int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000405{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100406 int ret;
407 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
408
409#if defined(MBEDTLS_THREADING_C)
410 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
411 return( ret );
412#endif
413
414 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
415
416#if defined(MBEDTLS_THREADING_C)
417 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
418 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
419#endif
420
421 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000422}
423
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200424#if defined(MBEDTLS_FS_IO)
425int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000426{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200427 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000428 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200429 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000430
431 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200432 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000433
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200434 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200435 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000436
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200437 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200438 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Andres Amaya Garciae0a727e2017-06-26 10:56:58 +0100439 else
440 ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000441
Andres Amaya Garciac17cc442017-06-27 16:57:26 +0100442exit:
Andres Amaya Garciae0a727e2017-06-26 10:56:58 +0100443 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200444
Paul Bakkerfc754a92011-12-05 13:23:51 +0000445 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200446 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000447}
448
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000450{
Andres Amaya Garciae0a727e2017-06-26 10:56:58 +0100451 int ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000452 FILE *f;
453 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200454 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000455
456 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200457 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000458
459 fseek( f, 0, SEEK_END );
460 n = (size_t) ftell( f );
461 fseek( f, 0, SEEK_SET );
462
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200463 if( n > MBEDTLS_CTR_DRBG_MAX_INPUT )
Andres Amaya Garciac17cc442017-06-27 16:57:26 +0100464 {
465 fclose( f );
466 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
467 }
468
469 if( fread( buf, 1, n, f ) != n )
Andres Amaya Garciae0a727e2017-06-26 10:56:58 +0100470 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
471 else
472 mbedtls_ctr_drbg_update( ctx, buf, n );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000473
Paul Bakkerfc754a92011-12-05 13:23:51 +0000474 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200475
Andres Amaya Garciae0a727e2017-06-26 10:56:58 +0100476 mbedtls_zeroize( buf, sizeof( buf ) );
477
478 if( ret != 0 )
479 return( ret );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000482}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200483#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000484
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200485#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000486
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000487static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000488 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
489 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
490 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
491 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
492 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
493 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
494 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
495 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
496 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
497 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
498 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
499 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
500
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000501static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000502 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
503 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
504 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
505 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
506 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
507 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
508 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
509 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
510
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100511static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000512 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
513 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
514
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100515static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000516 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
517 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
518
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100519static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000520 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
521 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
522
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100523static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000524 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
525 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
526
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100527static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200528static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
529 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000530{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100531 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000532 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100533 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000534 return( 0 );
535}
536
Paul Bakker7dc4c442014-02-01 22:50:26 +0100537#define CHK( c ) if( (c) != 0 ) \
538 { \
539 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200540 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100541 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100542 }
543
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000544/*
545 * Checkup routine
546 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200547int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000548{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200549 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000550 unsigned char buf[16];
551
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200552 mbedtls_ctr_drbg_init( &ctx );
553
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000554 /*
555 * Based on a NIST CTR_DRBG test vector (PR = True)
556 */
557 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200558 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000559
560 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200561 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000562 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200563 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
564 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
565 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
566 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000567
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100568 mbedtls_ctr_drbg_free( &ctx );
569
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000570 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200571 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000572
573 /*
574 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
575 */
576 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200577 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000578
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100579 mbedtls_ctr_drbg_init( &ctx );
580
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000581 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200582 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000583 (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200584 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
585 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
586 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100587 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000588
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100589 mbedtls_ctr_drbg_free( &ctx );
590
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000591 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200592 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000593
594 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200595 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000596
597 return( 0 );
598}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200599#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000600
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200601#endif /* MBEDTLS_CTR_DRBG_C */