blob: d7a94840cc9119a1455843aff9a239362bad4a50 [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"
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/*
Simon Butcher71c7ac52016-05-10 23:47:30 +010070 * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow
71 * NIST tests to succeed (which require known length fixed entropy)
Paul Bakker18d32912011-12-10 21:42:49 +000072 */
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 */
Dvir Markovich1b364992017-06-26 13:43:34 +030097 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
98 {
99 return( ret );
100 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000101
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200102 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300103 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000104 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300105 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000106 return( 0 );
107}
108
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200109int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker18d32912011-12-10 21:42:49 +0000110 int (*f_entropy)(void *, unsigned char *, size_t),
111 void *p_entropy,
112 const unsigned char *custom,
113 size_t len )
114{
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200115 return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy, custom, len,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200116 MBEDTLS_CTR_DRBG_ENTROPY_LEN ) );
Paul Bakker18d32912011-12-10 21:42:49 +0000117}
118
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200119void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
Paul Bakkerfff03662014-06-18 16:21:25 +0200120{
121 if( ctx == NULL )
122 return;
123
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100124#if defined(MBEDTLS_THREADING_C)
125 mbedtls_mutex_free( &ctx->mutex );
126#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200127 mbedtls_aes_free( &ctx->aes_ctx );
128 mbedtls_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Paul Bakkerfff03662014-06-18 16:21:25 +0200129}
130
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200131void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000132{
133 ctx->prediction_resistance = resistance;
134}
135
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200136void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000137{
138 ctx->entropy_len = len;
139}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200140
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200141void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000142{
143 ctx->reseed_interval = interval;
144}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200145
146static int block_cipher_df( unsigned char *output,
147 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000148{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200149 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
150 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
151 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
152 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100153 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200154 mbedtls_aes_context aes_ctx;
Dvir Markovich1b364992017-06-26 13:43:34 +0300155 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000156
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200157 int i, j;
158 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000159
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200160 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
161 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100162
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200163 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
164 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000165
166 /*
167 * Construct IV (16 bytes) and S in buffer
168 * IV = Counter (in 32-bits) padded to 16 with zeroes
169 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
170 * data || 0x80
171 * (Total is padded to a multiple of 16-bytes with zeroes)
172 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200173 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000174 *p++ = ( data_len >> 24 ) & 0xff;
175 *p++ = ( data_len >> 16 ) & 0xff;
176 *p++ = ( data_len >> 8 ) & 0xff;
177 *p++ = ( data_len ) & 0xff;
178 p += 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200179 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000180 memcpy( p, data, data_len );
181 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000182
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200183 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000184
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200185 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000186 key[i] = i;
187
Dvir Markovich1b364992017-06-26 13:43:34 +0300188 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
189 {
190 goto exit;
191 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000192
193 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200194 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000195 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200196 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000197 {
198 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200199 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000200 use_len = buf_len;
201
202 while( use_len > 0 )
203 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200204 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000205 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200206 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
207 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
208 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000209
Dvir Markovich1b364992017-06-26 13:43:34 +0300210 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ) ) != 0 )
211 {
212 goto exit;
213 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000214 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200215
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200216 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000217
218 /*
219 * Update IV
220 */
221 buf[3]++;
222 }
223
224 /*
225 * Do final encryption with reduced data
226 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300227 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
228 {
229 goto exit;
230 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200231 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000232 p = output;
233
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200234 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000235 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300236 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) ) != 0 )
237 {
238 goto exit;
239 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200240 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
241 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000242 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300243exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200244 mbedtls_aes_free( &aes_ctx );
Dvir Markovich1b364992017-06-26 13:43:34 +0300245 /*
246 * tidy up the stack
247 */
248 mbedtls_zeroize( buf, sizeof( buf ) );
249 mbedtls_zeroize( tmp, sizeof( tmp ) );
250 mbedtls_zeroize( key, sizeof( key ) );
251 mbedtls_zeroize( chain, sizeof( chain ) );
252 if( 0 != ret )
253 {
254 /*
255 * wipe partial seed from memory
256 */
257 mbedtls_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
258 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200259
Dvir Markovich1b364992017-06-26 13:43:34 +0300260 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000261}
262
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200263static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
264 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000265{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200266 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000267 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000268 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300269 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000270
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200271 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000272
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200273 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000274 {
275 /*
276 * Increase counter
277 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200278 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000279 if( ++ctx->counter[i - 1] != 0 )
280 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000281
282 /*
283 * Crypt counter block
284 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300285 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200286 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000287
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200288 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000289 }
290
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200291 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000292 tmp[i] ^= data[i];
293
294 /*
295 * Update key and counter
296 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300297 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200298 goto exit;
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
Gilles Peskined324c592018-09-11 15:34:17 +0200301exit:
302 mbedtls_zeroize( tmp, sizeof( tmp ) );
303 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000304}
305
Gilles Peskine9ce29722018-09-11 16:41:54 +0200306int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
307 const unsigned char *additional,
308 size_t add_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000309{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200310 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Gilles Peskine9ce29722018-09-11 16:41:54 +0200311 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000312
Gilles Peskine9ce29722018-09-11 16:41:54 +0200313 if( add_len == 0 )
314 return( 0 );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100315
Gilles Peskine9ce29722018-09-11 16:41:54 +0200316 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
317 goto exit;
318 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
319 goto exit;
320
321exit:
322 mbedtls_zeroize( add_input, sizeof( add_input ) );
323 return( ret );
324}
325
326/* Deprecated function, kept for backward compatibility. */
327void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
328 const unsigned char *additional,
329 size_t add_len )
330{
331 /* MAX_INPUT would be more logical here, but we have to match
332 * block_cipher_df()'s limits since we can't propagate errors */
333 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
334 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
335 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000336}
337
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200338int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000339 const unsigned char *additional, size_t len )
340{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200341 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000342 size_t seedlen = 0;
Dvir Markovich1b364992017-06-26 13:43:34 +0300343 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000344
Andres Amaya Garcia6a543362017-01-17 23:04:22 +0000345 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
346 len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200347 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000348
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200349 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000350
351 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200352 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000353 */
354 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
355 ctx->entropy_len ) )
356 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200357 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000358 }
359
360 seedlen += ctx->entropy_len;
361
362 /*
363 * Add additional data
364 */
365 if( additional && len )
366 {
367 memcpy( seed + seedlen, additional, len );
368 seedlen += len;
369 }
370
371 /*
372 * Reduce to 384 bits
373 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300374 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200375 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000376
377 /*
378 * Update state
379 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300380 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200381 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000382 ctx->reseed_counter = 1;
383
Gilles Peskined324c592018-09-11 15:34:17 +0200384exit:
385 mbedtls_zeroize( seed, sizeof( seed ) );
386 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000387}
Paul Bakker9af723c2014-05-01 13:03:14 +0200388
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200389int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000390 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000391 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000392{
393 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200394 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
395 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000396 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200397 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000398 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000399 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000400
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200401 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
402 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000403
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200404 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
405 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000406
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200407 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000408
409 if( ctx->reseed_counter > ctx->reseed_interval ||
410 ctx->prediction_resistance )
411 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200412 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300413 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000414 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300415 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000416 add_len = 0;
417 }
418
419 if( add_len > 0 )
420 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300421 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200422 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300423 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200424 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000425 }
426
427 while( output_len > 0 )
428 {
429 /*
430 * Increase counter
431 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200432 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000433 if( ++ctx->counter[i - 1] != 0 )
434 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000435
436 /*
437 * Crypt counter block
438 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300439 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200440 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000441
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200442 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200443 output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000444 /*
445 * Copy random block to destination
446 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000447 memcpy( p, tmp, use_len );
448 p += use_len;
449 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000450 }
451
Dvir Markovich1b364992017-06-26 13:43:34 +0300452 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200453 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000454
455 ctx->reseed_counter++;
456
Gilles Peskined324c592018-09-11 15:34:17 +0200457exit:
458 mbedtls_zeroize( add_input, sizeof( add_input ) );
459 mbedtls_zeroize( tmp, sizeof( tmp ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000460 return( 0 );
461}
462
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200463int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000464{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100465 int ret;
466 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
467
468#if defined(MBEDTLS_THREADING_C)
469 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
470 return( ret );
471#endif
472
473 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
474
475#if defined(MBEDTLS_THREADING_C)
476 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
477 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
478#endif
479
480 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000481}
482
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200483#if defined(MBEDTLS_FS_IO)
484int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000485{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200486 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000487 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200488 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000489
490 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200491 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000492
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200493 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200494 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000495
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200496 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200497 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100498 else
499 ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000500
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100501exit:
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100502 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200503
Paul Bakkerfc754a92011-12-05 13:23:51 +0000504 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200505 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000506}
507
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200508int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000509{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100510 int ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000511 FILE *f;
512 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200513 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000514
515 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200516 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000517
518 fseek( f, 0, SEEK_END );
519 n = (size_t) ftell( f );
520 fseek( f, 0, SEEK_SET );
521
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200522 if( n > MBEDTLS_CTR_DRBG_MAX_INPUT )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100523 {
524 fclose( f );
525 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
526 }
527
528 if( fread( buf, 1, n, f ) != n )
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100529 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
530 else
Gilles Peskine9ce29722018-09-11 16:41:54 +0200531 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000532
Paul Bakkerfc754a92011-12-05 13:23:51 +0000533 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200534
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100535 mbedtls_zeroize( buf, sizeof( buf ) );
536
537 if( ret != 0 )
538 return( ret );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200539
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200540 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000541}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200542#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000543
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200544#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000545
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000546static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000547 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
548 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
549 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
550 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
551 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
552 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
553 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
554 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
555 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
556 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
557 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
558 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
559
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000560static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000561 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
562 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
563 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
564 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
565 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
566 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
567 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
568 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
569
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100570static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000571 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
572 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
573
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100574static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000575 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
576 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
577
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100578static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000579 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
580 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
581
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100582static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000583 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
584 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
585
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100586static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200587static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
588 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000589{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100590 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000591 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100592 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000593 return( 0 );
594}
595
Paul Bakker7dc4c442014-02-01 22:50:26 +0100596#define CHK( c ) if( (c) != 0 ) \
597 { \
598 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200599 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100600 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100601 }
602
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000603/*
604 * Checkup routine
605 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200606int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000607{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200608 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000609 unsigned char buf[16];
610
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200611 mbedtls_ctr_drbg_init( &ctx );
612
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000613 /*
614 * Based on a NIST CTR_DRBG test vector (PR = True)
615 */
616 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200617 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000618
619 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200620 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000621 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200622 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
623 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
624 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
625 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000626
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100627 mbedtls_ctr_drbg_free( &ctx );
628
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000629 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200630 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000631
632 /*
633 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
634 */
635 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200636 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000637
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100638 mbedtls_ctr_drbg_init( &ctx );
639
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000640 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200641 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000642 (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200643 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
644 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
645 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100646 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000647
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100648 mbedtls_ctr_drbg_free( &ctx );
649
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000650 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200651 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000652
653 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200654 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000655
656 return( 0 );
657}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200658#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000659
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200660#endif /* MBEDTLS_CTR_DRBG_C */