blob: d0e5ba862d2c32aed6aae232e9cda5efeeab566b [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/*
Paul Sokolovsky8d6d8c82018-02-10 11:11:41 +020022 * The NIST SP 800-90 DRBGs are described in the following publication.
Paul Bakker0e04d0e2011-11-27 14:46:59 +000023 *
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"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050036#include "mbedtls/platform_util.h"
Paul Bakker0e04d0e2011-11-27 14:46:59 +000037
Rich Evans00ab4702015-02-06 13:43:58 +000038#include <string.h>
39
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020040#if defined(MBEDTLS_FS_IO)
Paul Bakkerfc754a92011-12-05 13:23:51 +000041#include <stdio.h>
42#endif
43
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if defined(MBEDTLS_SELF_TEST)
45#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010047#else
Rich Evans00ab4702015-02-06 13:43:58 +000048#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020049#define mbedtls_printf printf
50#endif /* MBEDTLS_PLATFORM_C */
51#endif /* MBEDTLS_SELF_TEST */
Paul Bakker7dc4c442014-02-01 22:50:26 +010052
Paul Bakker18d32912011-12-10 21:42:49 +000053/*
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020054 * CTR_DRBG context initialization
55 */
56void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
57{
58 memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010059
60#if defined(MBEDTLS_THREADING_C)
61 mbedtls_mutex_init( &ctx->mutex );
62#endif
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020063}
64
65/*
Simon Butcher71c7ac52016-05-10 23:47:30 +010066 * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow
67 * NIST tests to succeed (which require known length fixed entropy)
Paul Bakker18d32912011-12-10 21:42:49 +000068 */
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020069int mbedtls_ctr_drbg_seed_entropy_len(
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020070 mbedtls_ctr_drbg_context *ctx,
Paul Bakker0e04d0e2011-11-27 14:46:59 +000071 int (*f_entropy)(void *, unsigned char *, size_t),
72 void *p_entropy,
Paul Bakker1bc9efc2011-12-03 11:29:32 +000073 const unsigned char *custom,
Paul Bakker18d32912011-12-10 21:42:49 +000074 size_t len,
75 size_t entropy_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000076{
77 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020078 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Paul Bakker0e04d0e2011-11-27 14:46:59 +000079
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020080 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000081
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020082 mbedtls_aes_init( &ctx->aes_ctx );
Paul Bakkerc7ea99a2014-06-18 11:12:03 +020083
Paul Bakker0e04d0e2011-11-27 14:46:59 +000084 ctx->f_entropy = f_entropy;
85 ctx->p_entropy = p_entropy;
86
Paul Bakker18d32912011-12-10 21:42:49 +000087 ctx->entropy_len = entropy_len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020088 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
Paul Bakker0e04d0e2011-11-27 14:46:59 +000089
90 /*
91 * Initialize with an empty key
92 */
Dvir Markovich1b364992017-06-26 13:43:34 +030093 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
94 {
95 return( ret );
96 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +000097
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020098 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +030099 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000100 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300101 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000102 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 );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500124 mbedtls_platform_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;
Dvir Markovich1b364992017-06-26 13:43:34 +0300151 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000152
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200153 int i, j;
154 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000155
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200156 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
157 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100158
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200159 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
160 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000161
162 /*
163 * Construct IV (16 bytes) and S in buffer
164 * IV = Counter (in 32-bits) padded to 16 with zeroes
165 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
166 * data || 0x80
167 * (Total is padded to a multiple of 16-bytes with zeroes)
168 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200169 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000170 *p++ = ( data_len >> 24 ) & 0xff;
171 *p++ = ( data_len >> 16 ) & 0xff;
172 *p++ = ( data_len >> 8 ) & 0xff;
173 *p++ = ( data_len ) & 0xff;
174 p += 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200175 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000176 memcpy( p, data, data_len );
177 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000178
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200179 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000180
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200181 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000182 key[i] = i;
183
Dvir Markovich1b364992017-06-26 13:43:34 +0300184 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
185 {
186 goto exit;
187 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000188
189 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200190 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000191 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200192 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000193 {
194 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200195 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000196 use_len = buf_len;
197
198 while( use_len > 0 )
199 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200200 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000201 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200202 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
203 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
204 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000205
Dvir Markovich1b364992017-06-26 13:43:34 +0300206 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ) ) != 0 )
207 {
208 goto exit;
209 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000210 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200211
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200212 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000213
214 /*
215 * Update IV
216 */
217 buf[3]++;
218 }
219
220 /*
221 * Do final encryption with reduced data
222 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300223 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
224 {
225 goto exit;
226 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200227 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000228 p = output;
229
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200230 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000231 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300232 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) ) != 0 )
233 {
234 goto exit;
235 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200236 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
237 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000238 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300239exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200240 mbedtls_aes_free( &aes_ctx );
Dvir Markovich1b364992017-06-26 13:43:34 +0300241 /*
242 * tidy up the stack
243 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500244 mbedtls_platform_zeroize( buf, sizeof( buf ) );
245 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
246 mbedtls_platform_zeroize( key, sizeof( key ) );
247 mbedtls_platform_zeroize( chain, sizeof( chain ) );
Dvir Markovich1b364992017-06-26 13:43:34 +0300248 if( 0 != ret )
249 {
250 /*
251 * wipe partial seed from memory
252 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500253 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
Dvir Markovich1b364992017-06-26 13:43:34 +0300254 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200255
Dvir Markovich1b364992017-06-26 13:43:34 +0300256 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000257}
258
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200259static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
260 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000261{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200262 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000263 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000264 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300265 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000266
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200267 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000268
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200269 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000270 {
271 /*
272 * Increase counter
273 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200274 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000275 if( ++ctx->counter[i - 1] != 0 )
276 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000277
278 /*
279 * Crypt counter block
280 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300281 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 )
282 {
283 return( ret );
284 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000285
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200286 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000287 }
288
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200289 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000290 tmp[i] ^= data[i];
291
292 /*
293 * Update key and counter
294 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300295 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
296 {
297 return( ret );
298 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200299 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000300
301 return( 0 );
302}
303
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200304void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000305 const unsigned char *additional, size_t add_len )
306{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200307 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000308
309 if( add_len > 0 )
310 {
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100311 /* MAX_INPUT would be more logical here, but we have to match
312 * block_cipher_df()'s limits since we can't propagate errors */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200313 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
314 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100315
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000316 block_cipher_df( add_input, additional, add_len );
317 ctr_drbg_update_internal( ctx, add_input );
318 }
319}
320
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200321int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000322 const unsigned char *additional, size_t len )
323{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200324 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000325 size_t seedlen = 0;
Dvir Markovich1b364992017-06-26 13:43:34 +0300326 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000327
Andres Amaya Garcia6a543362017-01-17 23:04:22 +0000328 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
329 len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200330 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000331
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200332 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000333
334 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200335 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000336 */
337 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
338 ctx->entropy_len ) )
339 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200340 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000341 }
342
343 seedlen += ctx->entropy_len;
344
345 /*
346 * Add additional data
347 */
348 if( additional && len )
349 {
350 memcpy( seed + seedlen, additional, len );
351 seedlen += len;
352 }
353
354 /*
355 * Reduce to 384 bits
356 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300357 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
358 {
359 return( ret );
360 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000361
362 /*
363 * Update state
364 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300365 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
366 {
367 return( ret );
368 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000369 ctx->reseed_counter = 1;
370
371 return( 0 );
372}
Paul Bakker9af723c2014-05-01 13:03:14 +0200373
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200374int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000375 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000376 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000377{
378 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200379 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
380 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000381 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200382 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000383 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000384 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000385
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200386 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
387 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000388
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200389 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
390 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000391
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200392 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000393
394 if( ctx->reseed_counter > ctx->reseed_interval ||
395 ctx->prediction_resistance )
396 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200397 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300398 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000399 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300400 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000401 add_len = 0;
402 }
403
404 if( add_len > 0 )
405 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300406 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
407 {
408 return( ret );
409 }
410 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
411 {
412 return( ret );
413 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000414 }
415
416 while( output_len > 0 )
417 {
418 /*
419 * Increase counter
420 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200421 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000422 if( ++ctx->counter[i - 1] != 0 )
423 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000424
425 /*
426 * Crypt counter block
427 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300428 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 )
429 {
430 return( ret );
431 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000432
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200433 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200434 output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000435 /*
436 * Copy random block to destination
437 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000438 memcpy( p, tmp, use_len );
439 p += use_len;
440 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000441 }
442
Dvir Markovich1b364992017-06-26 13:43:34 +0300443 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
444 {
445 return( ret );
446 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000447
448 ctx->reseed_counter++;
449
450 return( 0 );
451}
452
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200453int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000454{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100455 int ret;
456 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
457
458#if defined(MBEDTLS_THREADING_C)
459 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
460 return( ret );
461#endif
462
463 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
464
465#if defined(MBEDTLS_THREADING_C)
466 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
467 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
468#endif
469
470 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000471}
472
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200473#if defined(MBEDTLS_FS_IO)
474int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000475{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200476 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000477 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200478 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000479
480 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000482
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200483 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200484 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000485
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200486 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200487 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100488 else
489 ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000490
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100491exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500492 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200493
Paul Bakkerfc754a92011-12-05 13:23:51 +0000494 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200495 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000496}
497
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200498int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000499{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100500 int ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000501 FILE *f;
502 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200503 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000504
505 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200506 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000507
508 fseek( f, 0, SEEK_END );
509 n = (size_t) ftell( f );
510 fseek( f, 0, SEEK_SET );
511
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200512 if( n > MBEDTLS_CTR_DRBG_MAX_INPUT )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100513 {
514 fclose( f );
515 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
516 }
517
518 if( fread( buf, 1, n, f ) != n )
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100519 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
520 else
521 mbedtls_ctr_drbg_update( ctx, buf, n );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000522
Paul Bakkerfc754a92011-12-05 13:23:51 +0000523 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200524
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500525 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100526
527 if( ret != 0 )
528 return( ret );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200529
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200530 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000531}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200532#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000533
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200534#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000535
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000536static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000537 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
538 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
539 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
540 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
541 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
542 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
543 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
544 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
545 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
546 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
547 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
548 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
549
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000550static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000551 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
552 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
553 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
554 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
555 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
556 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
557 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
558 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
559
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100560static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000561 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
562 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
563
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100564static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000565 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
566 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
567
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100568static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000569 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
570 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
571
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100572static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000573 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
574 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
575
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100576static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200577static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
578 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000579{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100580 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000581 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100582 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000583 return( 0 );
584}
585
Paul Bakker7dc4c442014-02-01 22:50:26 +0100586#define CHK( c ) if( (c) != 0 ) \
587 { \
588 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200589 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100590 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100591 }
592
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000593/*
594 * Checkup routine
595 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200596int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000597{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200598 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000599 unsigned char buf[16];
600
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200601 mbedtls_ctr_drbg_init( &ctx );
602
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000603 /*
604 * Based on a NIST CTR_DRBG test vector (PR = True)
605 */
606 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200607 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000608
609 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200610 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000611 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200612 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
613 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
614 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
615 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000616
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100617 mbedtls_ctr_drbg_free( &ctx );
618
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000619 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200620 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000621
622 /*
623 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
624 */
625 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200626 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000627
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100628 mbedtls_ctr_drbg_init( &ctx );
629
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000630 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200631 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000632 (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200633 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
634 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
635 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100636 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000637
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100638 mbedtls_ctr_drbg_free( &ctx );
639
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000640 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200641 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000642
643 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200644 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000645
646 return( 0 );
647}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200648#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000649
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200650#endif /* MBEDTLS_CTR_DRBG_C */