blob: fc3188eb394621b22902ce5d88f1b7abf03ddcd1 [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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200306void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000307 const unsigned char *additional, size_t add_len )
308{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200309 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000310
311 if( add_len > 0 )
312 {
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100313 /* MAX_INPUT would be more logical here, but we have to match
314 * block_cipher_df()'s limits since we can't propagate errors */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200315 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
316 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100317
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000318 block_cipher_df( add_input, additional, add_len );
319 ctr_drbg_update_internal( ctx, add_input );
Gilles Peskined324c592018-09-11 15:34:17 +0200320 mbedtls_zeroize( add_input, sizeof( add_input ) );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000321 }
322}
323
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200324int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000325 const unsigned char *additional, size_t len )
326{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200327 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000328 size_t seedlen = 0;
Dvir Markovich1b364992017-06-26 13:43:34 +0300329 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000330
Andres Amaya Garcia6a543362017-01-17 23:04:22 +0000331 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
332 len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200333 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000334
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200335 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000336
337 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200338 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000339 */
340 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
341 ctx->entropy_len ) )
342 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200343 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000344 }
345
346 seedlen += ctx->entropy_len;
347
348 /*
349 * Add additional data
350 */
351 if( additional && len )
352 {
353 memcpy( seed + seedlen, additional, len );
354 seedlen += len;
355 }
356
357 /*
358 * Reduce to 384 bits
359 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300360 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200361 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000362
363 /*
364 * Update state
365 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300366 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200367 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000368 ctx->reseed_counter = 1;
369
Gilles Peskined324c592018-09-11 15:34:17 +0200370exit:
371 mbedtls_zeroize( seed, sizeof( seed ) );
372 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000373}
Paul Bakker9af723c2014-05-01 13:03:14 +0200374
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200375int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000376 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000377 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000378{
379 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200380 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
381 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000382 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200383 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000384 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000385 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000386
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200387 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
388 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000389
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200390 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
391 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000392
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200393 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000394
395 if( ctx->reseed_counter > ctx->reseed_interval ||
396 ctx->prediction_resistance )
397 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200398 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300399 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000400 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300401 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000402 add_len = 0;
403 }
404
405 if( add_len > 0 )
406 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300407 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200408 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300409 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200410 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000411 }
412
413 while( output_len > 0 )
414 {
415 /*
416 * Increase counter
417 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200418 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000419 if( ++ctx->counter[i - 1] != 0 )
420 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000421
422 /*
423 * Crypt counter block
424 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300425 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200426 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000427
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200428 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200429 output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000430 /*
431 * Copy random block to destination
432 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000433 memcpy( p, tmp, use_len );
434 p += use_len;
435 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000436 }
437
Dvir Markovich1b364992017-06-26 13:43:34 +0300438 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined324c592018-09-11 15:34:17 +0200439 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000440
441 ctx->reseed_counter++;
442
Gilles Peskined324c592018-09-11 15:34:17 +0200443exit:
444 mbedtls_zeroize( add_input, sizeof( add_input ) );
445 mbedtls_zeroize( tmp, sizeof( tmp ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000446 return( 0 );
447}
448
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000450{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100451 int ret;
452 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
453
454#if defined(MBEDTLS_THREADING_C)
455 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
456 return( ret );
457#endif
458
459 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
460
461#if defined(MBEDTLS_THREADING_C)
462 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
463 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
464#endif
465
466 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000467}
468
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200469#if defined(MBEDTLS_FS_IO)
470int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000471{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200472 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000473 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200474 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000475
476 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200477 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000478
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200479 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200480 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000481
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200482 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200483 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100484 else
485 ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000486
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100487exit:
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100488 mbedtls_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200489
Paul Bakkerfc754a92011-12-05 13:23:51 +0000490 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200491 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000492}
493
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200494int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000495{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100496 int ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000497 FILE *f;
498 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200499 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000500
501 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200502 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000503
504 fseek( f, 0, SEEK_END );
505 n = (size_t) ftell( f );
506 fseek( f, 0, SEEK_SET );
507
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200508 if( n > MBEDTLS_CTR_DRBG_MAX_INPUT )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100509 {
510 fclose( f );
511 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
512 }
513
514 if( fread( buf, 1, n, f ) != n )
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100515 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
516 else
517 mbedtls_ctr_drbg_update( ctx, buf, n );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000518
Paul Bakkerfc754a92011-12-05 13:23:51 +0000519 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200520
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100521 mbedtls_zeroize( buf, sizeof( buf ) );
522
523 if( ret != 0 )
524 return( ret );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200525
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200526 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000527}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200528#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000529
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200530#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000531
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000532static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000533 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
534 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
535 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
536 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
537 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
538 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
539 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
540 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
541 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
542 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
543 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
544 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
545
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000546static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000547 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
548 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
549 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
550 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
551 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
552 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
553 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
554 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
555
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100556static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000557 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
558 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
559
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100560static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000561 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
562 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
563
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100564static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000565 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
566 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
567
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100568static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000569 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
570 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
571
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100572static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200573static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
574 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000575{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100576 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000577 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100578 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000579 return( 0 );
580}
581
Paul Bakker7dc4c442014-02-01 22:50:26 +0100582#define CHK( c ) if( (c) != 0 ) \
583 { \
584 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200585 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100586 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100587 }
588
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000589/*
590 * Checkup routine
591 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200592int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000593{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200594 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000595 unsigned char buf[16];
596
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200597 mbedtls_ctr_drbg_init( &ctx );
598
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000599 /*
600 * Based on a NIST CTR_DRBG test vector (PR = True)
601 */
602 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200603 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000604
605 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200606 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000607 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200608 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
609 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
610 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
611 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000612
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100613 mbedtls_ctr_drbg_free( &ctx );
614
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000615 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200616 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000617
618 /*
619 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
620 */
621 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200622 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000623
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100624 mbedtls_ctr_drbg_init( &ctx );
625
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000626 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200627 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000628 (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200629 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
630 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
631 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100632 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000633
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100634 mbedtls_ctr_drbg_free( &ctx );
635
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000636 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200637 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000638
639 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200640 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000641
642 return( 0 );
643}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200644#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000645
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200646#endif /* MBEDTLS_CTR_DRBG_C */