blob: 35890eb49a68bd936b32cbe1c0d576d610c29fae [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 */
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +020069int mbedtls_ctr_drbg_seed_entropy_len(
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020070 mbedtls_ctr_drbg_context *ctx,
Paul Bakker0e04d0e2011-11-27 14:46:59 +000071 int (*f_entropy)(void *, unsigned char *, size_t),
72 void *p_entropy,
Paul Bakker1bc9efc2011-12-03 11:29:32 +000073 const unsigned char *custom,
Paul Bakker18d32912011-12-10 21:42:49 +000074 size_t len,
75 size_t entropy_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000076{
77 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020078 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
Paul Bakker0e04d0e2011-11-27 14:46:59 +000079
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020080 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +000081
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020082 mbedtls_aes_init( &ctx->aes_ctx );
Paul Bakkerc7ea99a2014-06-18 11:12:03 +020083
Paul Bakker0e04d0e2011-11-27 14:46:59 +000084 ctx->f_entropy = f_entropy;
85 ctx->p_entropy = p_entropy;
86
Paul Bakker18d32912011-12-10 21:42:49 +000087 ctx->entropy_len = entropy_len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020088 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
Paul Bakker0e04d0e2011-11-27 14:46:59 +000089
90 /*
91 * Initialize with an empty key
92 */
Hanno Beckera08651f2018-10-05 09:38:59 +010093 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
94 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +030095 {
96 return( ret );
97 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +000098
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020099 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300100 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000101 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300102 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000103 return( 0 );
104}
105
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200106int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker18d32912011-12-10 21:42:49 +0000107 int (*f_entropy)(void *, unsigned char *, size_t),
108 void *p_entropy,
109 const unsigned char *custom,
110 size_t len )
111{
Hanno Beckera08651f2018-10-05 09:38:59 +0100112 return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy,
113 custom, len,
114 MBEDTLS_CTR_DRBG_ENTROPY_LEN ) );
Paul Bakker18d32912011-12-10 21:42:49 +0000115}
116
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200117void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
Paul Bakkerfff03662014-06-18 16:21:25 +0200118{
119 if( ctx == NULL )
120 return;
121
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100122#if defined(MBEDTLS_THREADING_C)
123 mbedtls_mutex_free( &ctx->mutex );
124#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200125 mbedtls_aes_free( &ctx->aes_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500126 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
Paul Bakkerfff03662014-06-18 16:21:25 +0200127}
128
Hanno Beckera08651f2018-10-05 09:38:59 +0100129void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx,
130 int resistance )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000131{
132 ctx->prediction_resistance = resistance;
133}
134
Hanno Beckera08651f2018-10-05 09:38:59 +0100135void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx,
136 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000137{
138 ctx->entropy_len = len;
139}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200140
Hanno Beckera08651f2018-10-05 09:38:59 +0100141void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx,
142 int interval )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000143{
144 ctx->reseed_interval = interval;
145}
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200146
147static int block_cipher_df( unsigned char *output,
148 const unsigned char *data, size_t data_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000149{
Hanno Beckera08651f2018-10-05 09:38:59 +0100150 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
151 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200152 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
153 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
154 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100155 unsigned char *p, *iv;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200156 mbedtls_aes_context aes_ctx;
Dvir Markovich1b364992017-06-26 13:43:34 +0300157 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000158
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200159 int i, j;
160 size_t buf_len, use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000161
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200162 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
163 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100164
Hanno Beckera08651f2018-10-05 09:38:59 +0100165 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
166 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200167 mbedtls_aes_init( &aes_ctx );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000168
169 /*
170 * Construct IV (16 bytes) and S in buffer
171 * IV = Counter (in 32-bits) padded to 16 with zeroes
172 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
173 * data || 0x80
174 * (Total is padded to a multiple of 16-bytes with zeroes)
175 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200176 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000177 *p++ = ( data_len >> 24 ) & 0xff;
178 *p++ = ( data_len >> 16 ) & 0xff;
179 *p++ = ( data_len >> 8 ) & 0xff;
180 *p++ = ( data_len ) & 0xff;
181 p += 3;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200182 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
Paul Bakker2bc7cf12011-11-29 10:50:51 +0000183 memcpy( p, data, data_len );
184 p[data_len] = 0x80;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000185
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200186 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000187
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200188 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000189 key[i] = i;
190
Hanno Beckera08651f2018-10-05 09:38:59 +0100191 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key,
192 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300193 {
194 goto exit;
195 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000196
197 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200198 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000199 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200200 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000201 {
202 p = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200203 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000204 use_len = buf_len;
205
206 while( use_len > 0 )
207 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200208 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000209 chain[i] ^= p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200210 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
211 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
212 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000213
Hanno Beckera08651f2018-10-05 09:38:59 +0100214 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
215 chain, chain ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300216 {
217 goto exit;
218 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000219 }
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200220
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200221 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000222
223 /*
224 * Update IV
225 */
226 buf[3]++;
227 }
228
229 /*
230 * Do final encryption with reduced data
231 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100232 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp,
233 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300234 {
235 goto exit;
236 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200237 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000238 p = output;
239
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200240 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000241 {
Hanno Beckera08651f2018-10-05 09:38:59 +0100242 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
243 iv, iv ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300244 {
245 goto exit;
246 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200247 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
248 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000249 }
Dvir Markovich1b364992017-06-26 13:43:34 +0300250exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200251 mbedtls_aes_free( &aes_ctx );
Dvir Markovich1b364992017-06-26 13:43:34 +0300252 /*
253 * tidy up the stack
254 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500255 mbedtls_platform_zeroize( buf, sizeof( buf ) );
256 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
257 mbedtls_platform_zeroize( key, sizeof( key ) );
258 mbedtls_platform_zeroize( chain, sizeof( chain ) );
Dvir Markovich1b364992017-06-26 13:43:34 +0300259 if( 0 != ret )
260 {
261 /*
262 * wipe partial seed from memory
263 */
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500264 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
Dvir Markovich1b364992017-06-26 13:43:34 +0300265 }
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200266
Dvir Markovich1b364992017-06-26 13:43:34 +0300267 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000268}
269
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200270static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
Hanno Beckera08651f2018-10-05 09:38:59 +0100271 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000272{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200273 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000274 unsigned char *p = tmp;
Paul Bakker369e14b2012-04-18 14:16:09 +0000275 int i, j;
Dvir Markovich1b364992017-06-26 13:43:34 +0300276 int ret = 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000277
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200278 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000279
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200280 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000281 {
282 /*
283 * Increase counter
284 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200285 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000286 if( ++ctx->counter[i - 1] != 0 )
287 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000288
289 /*
290 * Crypt counter block
291 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100292 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
293 ctx->counter, p ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300294 {
295 return( ret );
296 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000297
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200298 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000299 }
300
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200301 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000302 tmp[i] ^= data[i];
303
304 /*
305 * Update key and counter
306 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100307 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp,
308 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300309 {
310 return( ret );
311 }
Hanno Beckera08651f2018-10-05 09:38:59 +0100312 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
313 MBEDTLS_CTR_DRBG_BLOCKSIZE );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000314
315 return( 0 );
316}
317
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200318void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000319 const unsigned char *additional, size_t add_len )
320{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200321 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000322
323 if( add_len > 0 )
324 {
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100325 /* MAX_INPUT would be more logical here, but we have to match
326 * block_cipher_df()'s limits since we can't propagate errors */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200327 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
328 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
Manuel Pégourié-Gonnard5cb4b312014-11-25 17:41:50 +0100329
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000330 block_cipher_df( add_input, additional, add_len );
331 ctr_drbg_update_internal( ctx, add_input );
332 }
333}
334
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200335int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000336 const unsigned char *additional, size_t len )
337{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200338 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000339 size_t seedlen = 0;
Dvir Markovich1b364992017-06-26 13:43:34 +0300340 int ret;
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000341
Andres Amaya Garcia6a543362017-01-17 23:04:22 +0000342 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
343 len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200344 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000345
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200346 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000347
348 /*
Paul Bakker18f03412013-09-11 10:53:05 +0200349 * Gather entropy_len bytes of entropy to seed state
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000350 */
351 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
352 ctx->entropy_len ) )
353 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200354 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000355 }
356
357 seedlen += ctx->entropy_len;
358
359 /*
360 * Add additional data
361 */
362 if( additional && len )
363 {
364 memcpy( seed + seedlen, additional, len );
365 seedlen += len;
366 }
367
368 /*
369 * Reduce to 384 bits
370 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300371 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
372 {
373 return( ret );
374 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000375
376 /*
377 * Update state
378 */
Dvir Markovich1b364992017-06-26 13:43:34 +0300379 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
380 {
381 return( ret );
382 }
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000383 ctx->reseed_counter = 1;
384
385 return( 0 );
386}
Paul Bakker9af723c2014-05-01 13:03:14 +0200387
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200388int mbedtls_ctr_drbg_random_with_add( void *p_rng,
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000389 unsigned char *output, size_t output_len,
Paul Bakker1bc9efc2011-12-03 11:29:32 +0000390 const unsigned char *additional, size_t add_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000391{
392 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200393 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
394 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000395 unsigned char *p = output;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200396 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
Paul Bakker369e14b2012-04-18 14:16:09 +0000397 int i;
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000398 size_t use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000399
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200400 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
401 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000402
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200403 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
404 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000405
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200406 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000407
408 if( ctx->reseed_counter > ctx->reseed_interval ||
409 ctx->prediction_resistance )
410 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200411 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300412 {
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000413 return( ret );
Dvir Markovich1b364992017-06-26 13:43:34 +0300414 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000415 add_len = 0;
416 }
417
418 if( add_len > 0 )
419 {
Dvir Markovich1b364992017-06-26 13:43:34 +0300420 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
421 {
422 return( ret );
423 }
424 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
425 {
426 return( ret );
427 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000428 }
429
430 while( output_len > 0 )
431 {
432 /*
433 * Increase counter
434 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200435 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
Paul Bakker369e14b2012-04-18 14:16:09 +0000436 if( ++ctx->counter[i - 1] != 0 )
437 break;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000438
439 /*
440 * Crypt counter block
441 */
Hanno Beckera08651f2018-10-05 09:38:59 +0100442 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
443 ctx->counter, tmp ) ) != 0 )
Dvir Markovich1b364992017-06-26 13:43:34 +0300444 {
445 return( ret );
446 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000447
Hanno Beckera08651f2018-10-05 09:38:59 +0100448 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE )
449 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000450 /*
451 * Copy random block to destination
452 */
Paul Bakker23fd5ea2011-11-29 15:56:12 +0000453 memcpy( p, tmp, use_len );
454 p += use_len;
455 output_len -= use_len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000456 }
457
Dvir Markovich1b364992017-06-26 13:43:34 +0300458 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
459 {
460 return( ret );
461 }
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000462
463 ctx->reseed_counter++;
464
465 return( 0 );
466}
467
Hanno Beckera08651f2018-10-05 09:38:59 +0100468int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output,
469 size_t output_len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000470{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100471 int ret;
472 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
473
474#if defined(MBEDTLS_THREADING_C)
475 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
476 return( ret );
477#endif
478
479 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
480
481#if defined(MBEDTLS_THREADING_C)
482 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
483 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
484#endif
485
486 return( ret );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000487}
488
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200489#if defined(MBEDTLS_FS_IO)
Hanno Beckera08651f2018-10-05 09:38:59 +0100490int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx,
491 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000492{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200493 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000494 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200495 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000496
497 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200498 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000499
Hanno Beckera08651f2018-10-05 09:38:59 +0100500 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf,
501 MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200502 goto exit;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000503
Hanno Beckera08651f2018-10-05 09:38:59 +0100504 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) !=
505 MBEDTLS_CTR_DRBG_MAX_INPUT )
506 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200507 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
Hanno Beckera08651f2018-10-05 09:38:59 +0100508 }
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100509 else
Hanno Beckera08651f2018-10-05 09:38:59 +0100510 {
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100511 ret = 0;
Hanno Beckera08651f2018-10-05 09:38:59 +0100512 }
Paul Bakkerfc754a92011-12-05 13:23:51 +0000513
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100514exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500515 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200516
Paul Bakkerfc754a92011-12-05 13:23:51 +0000517 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200518 return( ret );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000519}
520
Hanno Beckera08651f2018-10-05 09:38:59 +0100521int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx,
522 const char *path )
Paul Bakkerfc754a92011-12-05 13:23:51 +0000523{
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100524 int ret = 0;
Paul Bakkerfc754a92011-12-05 13:23:51 +0000525 FILE *f;
526 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200527 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
Paul Bakkerfc754a92011-12-05 13:23:51 +0000528
529 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200530 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000531
532 fseek( f, 0, SEEK_END );
533 n = (size_t) ftell( f );
534 fseek( f, 0, SEEK_SET );
535
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200536 if( n > MBEDTLS_CTR_DRBG_MAX_INPUT )
Andres Amaya Garcia4e2c07c2017-06-27 16:57:26 +0100537 {
538 fclose( f );
539 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
540 }
541
542 if( fread( buf, 1, n, f ) != n )
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100543 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
544 else
545 mbedtls_ctr_drbg_update( ctx, buf, n );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000546
Paul Bakkerfc754a92011-12-05 13:23:51 +0000547 fclose( f );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200548
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500549 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Andres Amaya Garcia13f41e12017-06-26 10:56:58 +0100550
551 if( ret != 0 )
552 return( ret );
Paul Bakkerc72d3f72013-05-14 13:22:41 +0200553
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200554 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
Paul Bakkerfc754a92011-12-05 13:23:51 +0000555}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200556#endif /* MBEDTLS_FS_IO */
Paul Bakkerfc754a92011-12-05 13:23:51 +0000557
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200558#if defined(MBEDTLS_SELF_TEST)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000559
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000560static const unsigned char entropy_source_pr[96] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000561 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
562 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
563 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
564 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
565 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
566 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
567 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
568 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
569 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
570 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
571 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
572 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
573
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000574static const unsigned char entropy_source_nopr[64] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000575 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
576 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
577 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
578 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
579 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
580 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
581 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
582 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
583
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100584static const unsigned char nonce_pers_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000585 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
586 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
587
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100588static const unsigned char nonce_pers_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000589 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
590 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
591
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100592static const unsigned char result_pr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000593 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
594 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
595
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100596static const unsigned char result_nopr[16] =
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000597 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
598 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
599
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100600static size_t test_offset;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200601static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
602 size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000603{
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100604 const unsigned char *p = data;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000605 memcpy( buf, p + test_offset, len );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100606 test_offset += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000607 return( 0 );
608}
609
Paul Bakker7dc4c442014-02-01 22:50:26 +0100610#define CHK( c ) if( (c) != 0 ) \
611 { \
612 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200613 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100614 return( 1 ); \
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100615 }
616
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000617/*
618 * Checkup routine
619 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200620int mbedtls_ctr_drbg_self_test( int verbose )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000621{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200622 mbedtls_ctr_drbg_context ctx;
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000623 unsigned char buf[16];
624
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200625 mbedtls_ctr_drbg_init( &ctx );
626
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000627 /*
628 * Based on a NIST CTR_DRBG test vector (PR = True)
629 */
630 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200631 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000632
633 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200634 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Hanno Beckera08651f2018-10-05 09:38:59 +0100635 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200636 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
637 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
638 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
639 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000640
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100641 mbedtls_ctr_drbg_free( &ctx );
642
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000643 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200644 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000645
646 /*
647 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
648 */
649 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200650 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000651
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100652 mbedtls_ctr_drbg_init( &ctx );
653
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000654 test_offset = 0;
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200655 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
Hanno Beckera08651f2018-10-05 09:38:59 +0100656 (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200657 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
658 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
659 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100660 CHK( memcmp( buf, result_nopr, 16 ) );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000661
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100662 mbedtls_ctr_drbg_free( &ctx );
663
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000664 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200665 mbedtls_printf( "passed\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000666
667 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200668 mbedtls_printf( "\n" );
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000669
670 return( 0 );
671}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200672#endif /* MBEDTLS_SELF_TEST */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000673
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200674#endif /* MBEDTLS_CTR_DRBG_C */