blob: fead18f72388d529993d5351c0b9e86a2d083fab [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 */
Gilles Peskineed7da592018-08-03 20:16:52 +020069/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
70 * mbedtls_ctr_drbg_seed_entropy_len(ctx, f_entropy, p_entropy,
71 * custom, len, entropy_len)
72 * implements
73 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
74 * security_strength) -> initial_working_state
75 * with inputs
76 * custom[:len] = nonce || personalization_string
77 * where entropy_input comes from f_entropy for entropy_len bytes
78 * and with outputs
79 * ctx = initial_working_state
80 */
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020081int mbedtls_ctr_drbg_seed_entropy_len(
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020082 mbedtls_ctr_drbg_context *ctx,
Paul Bakker0e04d0e2011-11-27 14:46:59 +000083 int (*f_entropy)(void *, unsigned char *, size_t),
84 void *p_entropy,
Paul Bakker1bc9efc2011-12-03 11:29:32 +000085 const unsigned char *custom,
Paul Bakker18d32912011-12-10 21:42:49 +000086 size_t len,
87 size_t entropy_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000088{
89 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020090 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Paul Bakker0e04d0e2011-11-27 14:46:59 +000091
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020092 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000093
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020094 mbedtls_aes_init( &ctx->aes_ctx );
Paul Bakkerc7ea99a2014-06-18 11:12:03 +020095
Paul Bakker0e04d0e2011-11-27 14:46:59 +000096 ctx->f_entropy = f_entropy;
97 ctx->p_entropy = p_entropy;
98
Paul Bakker18d32912011-12-10 21:42:49 +000099 ctx->entropy_len = entropy_len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200100 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000101
102 /*
103 * Initialize with an empty key
104 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300105 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
106 {
107 return( ret );
108 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000109
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200110 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300111 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000112 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300113 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000114 return( 0 );
115}
116
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200117int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker18d32912011-12-10 21:42:49 +0000118 int (*f_entropy)(void *, unsigned char *, size_t),
119 void *p_entropy,
120 const unsigned char *custom,
121 size_t len )
122{
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200123 return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy, custom, len,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200124 MBEDTLS_CTR_DRBG_ENTROPY_LEN ) );
Paul Bakker18d32912011-12-10 21:42:49 +0000125}
126
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200127void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
Paul Bakkerfff03662014-06-18 16:21:25 +0200128{
129 if( ctx == NULL )
130 return;
131
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100132#if defined(MBEDTLS_THREADING_C)
133 mbedtls_mutex_free( &ctx->mutex );
134#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200135 mbedtls_aes_free( &ctx->aes_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500136 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Paul Bakkerfff03662014-06-18 16:21:25 +0200137}
138
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200139void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000140{
141 ctx->prediction_resistance = resistance;
142}
143
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200144void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000145{
146 ctx->entropy_len = len;
147}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200148
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200149void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000150{
151 ctx->reseed_interval = interval;
152}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200153
154static int block_cipher_df( unsigned char *output,
155 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000156{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200157 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
158 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
159 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
160 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100161 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200162 mbedtls_aes_context aes_ctx;
Dvir Markovich1b364992017-06-26 13:43:34 +0300163 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000164
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200165 int i, j;
166 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000167
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200168 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
169 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100170
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200171 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
172 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000173
174 /*
175 * Construct IV (16 bytes) and S in buffer
176 * IV = Counter (in 32-bits) padded to 16 with zeroes
177 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
178 * data || 0x80
179 * (Total is padded to a multiple of 16-bytes with zeroes)
180 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200181 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000182 *p++ = ( data_len >> 24 ) & 0xff;
183 *p++ = ( data_len >> 16 ) & 0xff;
184 *p++ = ( data_len >> 8 ) & 0xff;
185 *p++ = ( data_len ) & 0xff;
186 p += 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200187 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000188 memcpy( p, data, data_len );
189 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000190
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200191 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000192
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200193 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000194 key[i] = i;
195
Dvir Markovich1b364992017-06-26 13:43:34 +0300196 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
197 {
198 goto exit;
199 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000200
201 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200202 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000203 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200204 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000205 {
206 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200207 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000208 use_len = buf_len;
209
210 while( use_len > 0 )
211 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200212 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000213 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200214 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
215 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
216 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000217
Dvir Markovich1b364992017-06-26 13:43:34 +0300218 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ) ) != 0 )
219 {
220 goto exit;
221 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000222 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200223
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200224 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000225
226 /*
227 * Update IV
228 */
229 buf[3]++;
230 }
231
232 /*
233 * Do final encryption with reduced data
234 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300235 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
236 {
237 goto exit;
238 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200239 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000240 p = output;
241
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200242 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000243 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300244 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) ) != 0 )
245 {
246 goto exit;
247 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200248 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
249 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000250 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300251exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200252 mbedtls_aes_free( &aes_ctx );
Dvir Markovich1b364992017-06-26 13:43:34 +0300253 /*
254 * tidy up the stack
255 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500256 mbedtls_platform_zeroize( buf, sizeof( buf ) );
257 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
258 mbedtls_platform_zeroize( key, sizeof( key ) );
259 mbedtls_platform_zeroize( chain, sizeof( chain ) );
Dvir Markovich1b364992017-06-26 13:43:34 +0300260 if( 0 != ret )
261 {
262 /*
263 * wipe partial seed from memory
264 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500265 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
Dvir Markovich1b364992017-06-26 13:43:34 +0300266 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200267
Dvir Markovich1b364992017-06-26 13:43:34 +0300268 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000269}
270
Gilles Peskineed7da592018-08-03 20:16:52 +0200271/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
272 * ctr_drbg_update_internal(ctx, provided_data)
273 * implements
274 * CTR_DRBG_Update(provided_data, Key, V)
275 * with inputs and outputs
276 * ctx->aes_ctx = Key
277 * ctx->counter = V
278 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200279static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
280 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000281{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200282 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000283 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000284 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300285 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000286
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200287 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000288
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200289 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000290 {
291 /*
292 * Increase counter
293 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200294 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000295 if( ++ctx->counter[i - 1] != 0 )
296 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000297
298 /*
299 * Crypt counter block
300 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300301 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 )
302 {
303 return( ret );
304 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000305
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200306 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000307 }
308
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200309 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000310 tmp[i] ^= data[i];
311
312 /*
313 * Update key and counter
314 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300315 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
316 {
317 return( ret );
318 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200319 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000320
321 return( 0 );
322}
323
Gilles Peskineed7da592018-08-03 20:16:52 +0200324/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
325 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
326 * implements
327 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
328 * security_strength) -> initial_working_state
329 * with inputs
330 * ctx->counter = all-bits-0
331 * ctx->aes_ctx = context from all-bits-0 key
332 * additional[:add_len] = entropy_input || nonce || personalization_string
333 * and with outputs
334 * ctx = initial_working_state
335 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200336void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000337 const unsigned char *additional, size_t add_len )
338{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200339 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000340
341 if( add_len > 0 )
342 {
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100343 /* MAX_INPUT would be more logical here, but we have to match
344 * block_cipher_df()'s limits since we can't propagate errors */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200345 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
346 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100347
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000348 block_cipher_df( add_input, additional, add_len );
349 ctr_drbg_update_internal( ctx, add_input );
350 }
351}
352
Gilles Peskineed7da592018-08-03 20:16:52 +0200353/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
354 * mbedtls_ctr_drbg_reseed(ctx, additional, len)
355 * implements
356 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
357 * -> new_working_state
358 * with inputs
359 * ctx contains working_state
360 * additional[:len] = additional_input
361 * and entropy_input comes from calling ctx->f_entropy
362 * and with output
363 * ctx contains new_working_state
364 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200365int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000366 const unsigned char *additional, size_t len )
367{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200368 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000369 size_t seedlen = 0;
Dvir Markovich1b364992017-06-26 13:43:34 +0300370 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000371
Andres Amaya Garcia6a543362017-01-17 23:04:22 +0000372 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
373 len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200374 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000375
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200376 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000377
378 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200379 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000380 */
381 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
382 ctx->entropy_len ) )
383 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200384 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000385 }
386
387 seedlen += ctx->entropy_len;
388
389 /*
390 * Add additional data
391 */
392 if( additional && len )
393 {
394 memcpy( seed + seedlen, additional, len );
395 seedlen += len;
396 }
397
398 /*
399 * Reduce to 384 bits
400 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300401 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
402 {
403 return( ret );
404 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000405
406 /*
407 * Update state
408 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300409 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
410 {
411 return( ret );
412 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000413 ctx->reseed_counter = 1;
414
415 return( 0 );
416}
Paul Bakker9af723c2014-05-01 13:03:14 +0200417
Gilles Peskineed7da592018-08-03 20:16:52 +0200418/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
419 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
420 * implements
421 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
422 * -> working_state_after_reseed
423 * if required, then
424 * CTR_DRBG_Generate(working_state_after_reseed,
425 * requested_number_of_bits, additional_input)
426 * -> status, returned_bits, new_working_state
427 * with inputs
428 * ctx contains working_state
429 * requested_number_of_bits = 8 * output_len
430 * additional[:add_len] = additional_input
431 * and entropy_input comes from calling ctx->f_entropy
432 * and with outputs
433 * status = SUCCESS (this function does the reseed internally)
434 * returned_bits = output[:output_len]
435 * ctx contains new_working_state
436 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200437int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000438 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000439 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000440{
441 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200442 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
443 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000444 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200445 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000446 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000447 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000448
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
450 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000451
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200452 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
453 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000454
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200455 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000456
457 if( ctx->reseed_counter > ctx->reseed_interval ||
458 ctx->prediction_resistance )
459 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200460 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300461 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000462 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300463 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000464 add_len = 0;
465 }
466
467 if( add_len > 0 )
468 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300469 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
470 {
471 return( ret );
472 }
473 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
474 {
475 return( ret );
476 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000477 }
478
479 while( output_len > 0 )
480 {
481 /*
482 * Increase counter
483 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200484 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000485 if( ++ctx->counter[i - 1] != 0 )
486 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000487
488 /*
489 * Crypt counter block
490 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300491 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 )
492 {
493 return( ret );
494 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000495
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200496 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200497 output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000498 /*
499 * Copy random block to destination
500 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000501 memcpy( p, tmp, use_len );
502 p += use_len;
503 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000504 }
505
Dvir Markovich1b364992017-06-26 13:43:34 +0300506 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
507 {
508 return( ret );
509 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000510
511 ctx->reseed_counter++;
512
513 return( 0 );
514}
515
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200516int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000517{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100518 int ret;
519 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
520
521#if defined(MBEDTLS_THREADING_C)
522 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
523 return( ret );
524#endif
525
526 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
527
528#if defined(MBEDTLS_THREADING_C)
529 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
530 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
531#endif
532
533 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000534}
535
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200536#if defined(MBEDTLS_FS_IO)
537int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000538{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200539 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000540 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200541 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000542
543 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200544 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000545
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200546 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200547 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000548
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200549 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200550 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100551 else
552 ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000553
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100554exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500555 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200556
Paul Bakkerfc754a92011-12-05 13:23:51 +0000557 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200558 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000559}
560
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200561int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000562{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100563 int ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000564 FILE *f;
565 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200566 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000567
568 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200569 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000570
571 fseek( f, 0, SEEK_END );
572 n = (size_t) ftell( f );
573 fseek( f, 0, SEEK_SET );
574
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200575 if( n > MBEDTLS_CTR_DRBG_MAX_INPUT )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100576 {
577 fclose( f );
578 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
579 }
580
581 if( fread( buf, 1, n, f ) != n )
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100582 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
583 else
584 mbedtls_ctr_drbg_update( ctx, buf, n );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000585
Paul Bakkerfc754a92011-12-05 13:23:51 +0000586 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200587
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500588 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100589
590 if( ret != 0 )
591 return( ret );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200592
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200593 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000594}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200595#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000596
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200597#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000598
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000599static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000600 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
601 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
602 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
603 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
604 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
605 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
606 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
607 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
608 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
609 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
610 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
611 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
612
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000613static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000614 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
615 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
616 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
617 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
618 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
619 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
620 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
621 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
622
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100623static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000624 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
625 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
626
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100627static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000628 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
629 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
630
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100631static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000632 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
633 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
634
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100635static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000636 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
637 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
638
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100639static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200640static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
641 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000642{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100643 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000644 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100645 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000646 return( 0 );
647}
648
Paul Bakker7dc4c442014-02-01 22:50:26 +0100649#define CHK( c ) if( (c) != 0 ) \
650 { \
651 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200652 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100653 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100654 }
655
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000656/*
657 * Checkup routine
658 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200659int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000660{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200661 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000662 unsigned char buf[16];
663
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200664 mbedtls_ctr_drbg_init( &ctx );
665
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000666 /*
667 * Based on a NIST CTR_DRBG test vector (PR = True)
668 */
669 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200670 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000671
672 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200673 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000674 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200675 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
676 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
677 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
678 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000679
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100680 mbedtls_ctr_drbg_free( &ctx );
681
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000682 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200683 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000684
685 /*
686 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
687 */
688 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200689 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000690
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100691 mbedtls_ctr_drbg_init( &ctx );
692
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000693 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200694 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000695 (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200696 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
697 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
698 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100699 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000700
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100701 mbedtls_ctr_drbg_free( &ctx );
702
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000703 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200704 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000705
706 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200707 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000708
709 return( 0 );
710}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200711#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000712
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200713#endif /* MBEDTLS_CTR_DRBG_C */