blob: fb121575bbbe8d737178409175efd5692d1c3278 [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 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200302 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000303
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200304 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000305 }
306
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200307 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000308 tmp[i] ^= data[i];
309
310 /*
311 * Update key and counter
312 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300313 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200314 goto exit;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200315 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000316
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200317exit:
318 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
319 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000320}
321
Gilles Peskineed7da592018-08-03 20:16:52 +0200322/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
323 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
324 * implements
325 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
326 * security_strength) -> initial_working_state
327 * with inputs
328 * ctx->counter = all-bits-0
329 * ctx->aes_ctx = context from all-bits-0 key
330 * additional[:add_len] = entropy_input || nonce || personalization_string
331 * and with outputs
332 * ctx = initial_working_state
333 */
Gilles Peskined9199932018-09-11 16:41:54 +0200334int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
335 const unsigned char *additional,
336 size_t add_len )
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000337{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200338 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Gilles Peskined9199932018-09-11 16:41:54 +0200339 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000340
Gilles Peskined9199932018-09-11 16:41:54 +0200341 if( add_len == 0 )
342 return( 0 );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100343
Gilles Peskined9199932018-09-11 16:41:54 +0200344 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
345 goto exit;
346 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
347 goto exit;
348
349exit:
350 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
351 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000352}
353
Gilles Peskined9199932018-09-11 16:41:54 +0200354#if !defined(MBEDTLS_DEPRECATED_REMOVED)
355void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
356 const unsigned char *additional,
357 size_t add_len )
358{
359 /* MAX_INPUT would be more logical here, but we have to match
360 * block_cipher_df()'s limits since we can't propagate errors */
361 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
362 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
363 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
364}
365#endif /* MBEDTLS_DEPRECATED_REMOVED */
366
Gilles Peskineed7da592018-08-03 20:16:52 +0200367/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
368 * mbedtls_ctr_drbg_reseed(ctx, additional, len)
369 * implements
370 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
371 * -> new_working_state
372 * with inputs
373 * ctx contains working_state
374 * additional[:len] = additional_input
375 * and entropy_input comes from calling ctx->f_entropy
376 * and with output
377 * ctx contains new_working_state
378 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200379int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000380 const unsigned char *additional, size_t len )
381{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200382 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000383 size_t seedlen = 0;
Dvir Markovich1b364992017-06-26 13:43:34 +0300384 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000385
Andres Amaya Garcia6a543362017-01-17 23:04:22 +0000386 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
387 len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200388 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000389
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200390 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000391
392 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200393 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000394 */
395 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
396 ctx->entropy_len ) )
397 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200398 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000399 }
400
401 seedlen += ctx->entropy_len;
402
403 /*
404 * Add additional data
405 */
406 if( additional && len )
407 {
408 memcpy( seed + seedlen, additional, len );
409 seedlen += len;
410 }
411
412 /*
413 * Reduce to 384 bits
414 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300415 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200416 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000417
418 /*
419 * Update state
420 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300421 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200422 goto exit;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000423 ctx->reseed_counter = 1;
424
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200425exit:
426 mbedtls_platform_zeroize( seed, sizeof( seed ) );
427 return( ret );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000428}
Paul Bakker9af723c2014-05-01 13:03:14 +0200429
Gilles Peskineed7da592018-08-03 20:16:52 +0200430/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
431 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
432 * implements
433 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
434 * -> working_state_after_reseed
435 * if required, then
436 * CTR_DRBG_Generate(working_state_after_reseed,
437 * requested_number_of_bits, additional_input)
438 * -> status, returned_bits, new_working_state
439 * with inputs
440 * ctx contains working_state
441 * requested_number_of_bits = 8 * output_len
442 * additional[:add_len] = additional_input
443 * and entropy_input comes from calling ctx->f_entropy
444 * and with outputs
445 * status = SUCCESS (this function does the reseed internally)
446 * returned_bits = output[:output_len]
447 * ctx contains new_working_state
448 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000450 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000451 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000452{
453 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200454 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
455 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000456 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200457 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000458 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000459 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000460
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200461 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
462 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000463
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200464 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
465 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000466
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200467 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000468
469 if( ctx->reseed_counter > ctx->reseed_interval ||
470 ctx->prediction_resistance )
471 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200472 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300473 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000474 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300475 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000476 add_len = 0;
477 }
478
479 if( add_len > 0 )
480 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300481 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200482 goto exit;
Dvir Markovich1b364992017-06-26 13:43:34 +0300483 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200484 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000485 }
486
487 while( output_len > 0 )
488 {
489 /*
490 * Increase counter
491 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200492 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000493 if( ++ctx->counter[i - 1] != 0 )
494 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000495
496 /*
497 * Crypt counter block
498 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300499 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200500 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000501
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200502 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200503 output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000504 /*
505 * Copy random block to destination
506 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000507 memcpy( p, tmp, use_len );
508 p += use_len;
509 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000510 }
511
Dvir Markovich1b364992017-06-26 13:43:34 +0300512 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200513 goto exit;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000514
515 ctx->reseed_counter++;
516
Gilles Peskined9aa84d2018-09-11 15:34:17 +0200517exit:
518 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
519 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000520 return( 0 );
521}
522
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200523int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000524{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100525 int ret;
526 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
527
528#if defined(MBEDTLS_THREADING_C)
529 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
530 return( ret );
531#endif
532
533 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
534
535#if defined(MBEDTLS_THREADING_C)
536 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
537 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
538#endif
539
540 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000541}
542
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200543#if defined(MBEDTLS_FS_IO)
544int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000545{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200546 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000547 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200548 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000549
550 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200551 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000552
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200553 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200554 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000555
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200556 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200557 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100558 else
559 ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000560
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100561exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500562 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200563
Paul Bakkerfc754a92011-12-05 13:23:51 +0000564 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200565 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000566}
567
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200568int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000569{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100570 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200571 FILE *f = NULL;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000572 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200573 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200574 unsigned char c;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000575
576 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200577 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000578
Gilles Peskine82204662018-09-11 18:43:09 +0200579 n = fread( buf, 1, sizeof( buf ), f );
580 if( fread( &c, 1, 1, f ) != 0 )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100581 {
Gilles Peskine82204662018-09-11 18:43:09 +0200582 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
583 goto exit;
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100584 }
Gilles Peskine82204662018-09-11 18:43:09 +0200585 if( n == 0 || ferror( f ) )
586 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100587 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200588 goto exit;
589 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000590 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200591 f = NULL;
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200592
Gilles Peskine82204662018-09-11 18:43:09 +0200593 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
594
595exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500596 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200597 if( f != NULL )
598 fclose( f );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100599 if( ret != 0 )
600 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200601 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000602}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200603#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000604
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200605#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000606
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000607static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000608 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
609 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
610 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
611 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
612 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
613 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
614 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
615 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
616 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
617 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
618 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
619 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
620
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000621static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000622 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
623 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
624 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
625 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
626 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
627 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
628 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
629 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
630
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100631static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000632 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
633 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
634
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100635static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000636 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
637 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
638
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100639static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000640 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
641 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
642
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100643static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000644 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
645 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
646
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100647static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200648static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
649 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000650{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100651 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000652 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100653 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000654 return( 0 );
655}
656
Paul Bakker7dc4c442014-02-01 22:50:26 +0100657#define CHK( c ) if( (c) != 0 ) \
658 { \
659 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200660 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100661 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100662 }
663
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000664/*
665 * Checkup routine
666 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200667int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000668{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200669 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000670 unsigned char buf[16];
671
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200672 mbedtls_ctr_drbg_init( &ctx );
673
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000674 /*
675 * Based on a NIST CTR_DRBG test vector (PR = True)
676 */
677 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200678 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000679
680 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200681 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000682 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200683 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
684 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
685 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
686 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000687
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100688 mbedtls_ctr_drbg_free( &ctx );
689
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000690 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200691 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000692
693 /*
694 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
695 */
696 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200697 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000698
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100699 mbedtls_ctr_drbg_init( &ctx );
700
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000701 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200702 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000703 (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200704 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
705 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
706 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100707 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000708
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100709 mbedtls_ctr_drbg_free( &ctx );
710
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000711 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200712 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000713
714 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200715 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000716
717 return( 0 );
718}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200719#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000720
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200721#endif /* MBEDTLS_CTR_DRBG_C */