blob: a264dedb075e529e3ee0fb72ed271e5a8908fb53 [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;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000571 FILE *f;
572 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200573 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000574
575 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200576 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000577
578 fseek( f, 0, SEEK_END );
579 n = (size_t) ftell( f );
580 fseek( f, 0, SEEK_SET );
581
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200582 if( n > MBEDTLS_CTR_DRBG_MAX_INPUT )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100583 {
584 fclose( f );
585 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
586 }
587
588 if( fread( buf, 1, n, f ) != n )
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100589 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
590 else
Gilles Peskined9199932018-09-11 16:41:54 +0200591 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000592
Paul Bakkerfc754a92011-12-05 13:23:51 +0000593 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200594
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500595 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100596
597 if( ret != 0 )
598 return( ret );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200599
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200600 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000601}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200602#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000603
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200604#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000605
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000606static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000607 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
608 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
609 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
610 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
611 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
612 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
613 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
614 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
615 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
616 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
617 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
618 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
619
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000620static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000621 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
622 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
623 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
624 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
625 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
626 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
627 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
628 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
629
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100630static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000631 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
632 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
633
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100634static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000635 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
636 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
637
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100638static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000639 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
640 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
641
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100642static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000643 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
644 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
645
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100646static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200647static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
648 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000649{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100650 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000651 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100652 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000653 return( 0 );
654}
655
Paul Bakker7dc4c442014-02-01 22:50:26 +0100656#define CHK( c ) if( (c) != 0 ) \
657 { \
658 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200659 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100660 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100661 }
662
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000663/*
664 * Checkup routine
665 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200666int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000667{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200668 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000669 unsigned char buf[16];
670
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200671 mbedtls_ctr_drbg_init( &ctx );
672
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000673 /*
674 * Based on a NIST CTR_DRBG test vector (PR = True)
675 */
676 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200677 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000678
679 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200680 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000681 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200682 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
683 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
684 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
685 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000686
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100687 mbedtls_ctr_drbg_free( &ctx );
688
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000689 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200690 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000691
692 /*
693 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
694 */
695 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200696 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000697
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100698 mbedtls_ctr_drbg_init( &ctx );
699
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000700 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200701 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000702 (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200703 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
704 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
705 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100706 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000707
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100708 mbedtls_ctr_drbg_free( &ctx );
709
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000710 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200711 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000712
713 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200714 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000715
716 return( 0 );
717}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200718#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000719
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200720#endif /* MBEDTLS_CTR_DRBG_C */