blob: e80d81ee6363d72dadd88b93ee3f14d77ac09ed4 [file] [log] [blame]
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +01001/*
2 * HMAC_DRBG implementation (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.
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010020 */
21
22/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010023 * The NIST SP 800-90A DRBGs are described in the following publication.
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010024 * http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010025 * References below are based on rev. 1 (January 2012).
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010026 */
27
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020028#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000029#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020030#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020031#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020032#endif
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010033
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020034#if defined(MBEDTLS_HMAC_DRBG_C)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010035
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000036#include "mbedtls/hmac_drbg.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050037#include "mbedtls/platform_util.h"
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010038
Rich Evans00ab4702015-02-06 13:43:58 +000039#include <string.h>
40
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#if defined(MBEDTLS_FS_IO)
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +010042#include <stdio.h>
43#endif
44
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020045#if defined(MBEDTLS_SELF_TEST)
46#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000047#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010048#else
Rich Evans00ab4702015-02-06 13:43:58 +000049#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020050#define mbedtls_printf printf
51#endif /* MBEDTLS_SELF_TEST */
52#endif /* MBEDTLS_PLATFORM_C */
Paul Bakker7dc4c442014-02-01 22:50:26 +010053
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010054/*
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +020055 * HMAC_DRBG context initialization
56 */
57void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx )
58{
59 memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010060
61#if defined(MBEDTLS_THREADING_C)
62 mbedtls_mutex_init( &ctx->mutex );
63#endif
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +020064}
65
66/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010067 * HMAC_DRBG update, using optional additional data (10.1.2.2)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010068 */
Gilles Peskine48dbe3b2018-09-13 22:19:57 +020069int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx,
70 const unsigned char *additional,
71 size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010072{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020073 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010074 unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
75 unsigned char sep[1];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020076 unsigned char K[MBEDTLS_MD_MAX_SIZE];
Gilles Peskine48dbe3b2018-09-13 22:19:57 +020077 int ret;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010078
79 for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
80 {
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010081 /* Step 1 or 4 */
Gilles Peskine48dbe3b2018-09-13 22:19:57 +020082 if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
83 goto exit;
84 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
85 ctx->V, md_len ) ) != 0 )
86 goto exit;
87 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
88 sep, 1 ) ) != 0 )
89 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010090 if( rounds == 2 )
Gilles Peskine48dbe3b2018-09-13 22:19:57 +020091 {
92 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
93 additional, add_len ) ) != 0 )
94 goto exit;
95 }
96 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, K ) ) != 0 )
97 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010098
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010099 /* Step 2 or 5 */
Gilles Peskine48dbe3b2018-09-13 22:19:57 +0200100 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ) ) != 0 )
101 goto exit;
102 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
103 ctx->V, md_len ) ) != 0 )
104 goto exit;
105 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
106 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100107 }
Gilles Peskinebae04832018-09-11 15:35:41 +0200108
Gilles Peskine48dbe3b2018-09-13 22:19:57 +0200109exit:
Gilles Peskinebae04832018-09-11 15:35:41 +0200110 mbedtls_platform_zeroize( K, sizeof( K ) );
Gilles Peskine48dbe3b2018-09-13 22:19:57 +0200111 return( ret );
112}
113
114void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
115 const unsigned char *additional,
116 size_t add_len )
117{
118 (void) mbedtls_hmac_drbg_update_ret( ctx, additional, add_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100119}
120
121/*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100122 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100123 */
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200124int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200125 const mbedtls_md_info_t * md_info,
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100126 const unsigned char *data, size_t data_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100127{
128 int ret;
129
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200130 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100131 return( ret );
132
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100133 /*
134 * Set initial working state.
135 * Use the V memory location, which is currently all 0, to initialize the
136 * MD context with an all-zero key. Then set V to its initial value.
137 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200138 mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, mbedtls_md_get_size( md_info ) );
139 memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100140
Gilles Peskine48dbe3b2018-09-13 22:19:57 +0200141 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, data, data_len ) ) != 0 )
142 return( ret );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100143
144 return( 0 );
145}
146
147/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100148 * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100149 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200150int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100151 const unsigned char *additional, size_t len )
152{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200153 unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100154 size_t seedlen;
Gilles Peskine48dbe3b2018-09-13 22:19:57 +0200155 int ret;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100156
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100157 /* III. Check input length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200158 if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
159 ctx->entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100160 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200161 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100162 }
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100163
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200164 memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100165
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100166 /* IV. Gather entropy_len bytes of entropy for the seed */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100167 if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200168 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100169
170 seedlen = ctx->entropy_len;
171
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100172 /* 1. Concatenate entropy and additional data if any */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100173 if( additional != NULL && len != 0 )
174 {
175 memcpy( seed + seedlen, additional, len );
176 seedlen += len;
177 }
178
179 /* 2. Update state */
Gilles Peskine48dbe3b2018-09-13 22:19:57 +0200180 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, seed, seedlen ) ) != 0 )
181 goto exit;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100182
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100183 /* 3. Reset reseed_counter */
184 ctx->reseed_counter = 1;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100185
Gilles Peskine48dbe3b2018-09-13 22:19:57 +0200186exit:
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100187 /* 4. Done */
Gilles Peskinebae04832018-09-11 15:35:41 +0200188 mbedtls_platform_zeroize( seed, seedlen );
Gilles Peskine48dbe3b2018-09-13 22:19:57 +0200189 return( ret );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100190}
191
192/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100193 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100194 */
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200195int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200196 const mbedtls_md_info_t * md_info,
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100197 int (*f_entropy)(void *, unsigned char *, size_t),
198 void *p_entropy,
199 const unsigned char *custom,
200 size_t len )
201{
202 int ret;
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100203 size_t entropy_len, md_size;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100204
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200205 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100206 return( ret );
207
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200208 md_size = mbedtls_md_get_size( md_info );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100209
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100210 /*
211 * Set initial working state.
212 * Use the V memory location, which is currently all 0, to initialize the
213 * MD context with an all-zero key. Then set V to its initial value.
214 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200215 mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100216 memset( ctx->V, 0x01, md_size );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100217
218 ctx->f_entropy = f_entropy;
219 ctx->p_entropy = p_entropy;
220
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200221 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100222
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100223 /*
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100224 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
225 * each hash function, then according to SP800-90A rev1 10.1 table 2,
226 * min_entropy_len (in bits) is security_strength.
227 *
228 * (This also matches the sizes used in the NIST test vectors.)
229 */
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100230 entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
231 md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
232 32; /* better (256+) -> 256 bits */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100233
234 /*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100235 * For initialisation, use more entropy to emulate a nonce
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100236 * (Again, matches test vectors.)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100237 */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100238 ctx->entropy_len = entropy_len * 3 / 2;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100239
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200240 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100241 return( ret );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100242
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100243 ctx->entropy_len = entropy_len;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100244
245 return( 0 );
246}
247
248/*
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100249 * Set prediction resistance
250 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200251void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100252 int resistance )
253{
254 ctx->prediction_resistance = resistance;
255}
256
257/*
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100258 * Set entropy length grabbed for reseeds
259 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200260void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100261{
262 ctx->entropy_len = len;
263}
264
265/*
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100266 * Set reseed interval
267 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200268void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval )
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100269{
270 ctx->reseed_interval = interval;
271}
272
273/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100274 * HMAC_DRBG random function with optional additional data:
275 * 10.1.2.5 (arabic) + 9.3 (Roman)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100276 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200277int mbedtls_hmac_drbg_random_with_add( void *p_rng,
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100278 unsigned char *output, size_t out_len,
279 const unsigned char *additional, size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100280{
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100281 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200282 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
283 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100284 size_t left = out_len;
285 unsigned char *out = output;
286
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100287 /* II. Check request length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200288 if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST )
289 return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100290
291 /* III. Check input length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200292 if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
293 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100294
295 /* 1. (aka VII and IX) Check reseed counter and PR */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100296 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200297 ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100298 ctx->reseed_counter > ctx->reseed_interval ) )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100299 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200300 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100301 return( ret );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100302
303 add_len = 0; /* VII.4 */
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100304 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100305
306 /* 2. Use additional data if any */
307 if( additional != NULL && add_len != 0 )
Gilles Peskine48dbe3b2018-09-13 22:19:57 +0200308 {
309 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
310 additional, add_len ) ) != 0 )
311 goto exit;
312 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100313
314 /* 3, 4, 5. Generate bytes */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100315 while( left != 0 )
316 {
317 size_t use_len = left > md_len ? md_len : left;
318
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200319 mbedtls_md_hmac_reset( &ctx->md_ctx );
320 mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
321 mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100322
323 memcpy( out, ctx->V, use_len );
324 out += use_len;
325 left -= use_len;
326 }
327
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100328 /* 6. Update */
Gilles Peskine48dbe3b2018-09-13 22:19:57 +0200329 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
330 additional, add_len ) ) != 0 )
331 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100332
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100333 /* 7. Update reseed counter */
334 ctx->reseed_counter++;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100335
Gilles Peskine48dbe3b2018-09-13 22:19:57 +0200336exit:
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100337 /* 8. Done */
Gilles Peskine48dbe3b2018-09-13 22:19:57 +0200338 return( ret );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100339}
340
341/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100342 * HMAC_DRBG random function
343 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200344int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100345{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100346 int ret;
347 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
348
349#if defined(MBEDTLS_THREADING_C)
350 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
351 return( ret );
352#endif
353
354 ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
355
356#if defined(MBEDTLS_THREADING_C)
357 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
358 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
359#endif
360
361 return( ret );
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100362}
363
364/*
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100365 * Free an HMAC_DRBG context
366 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200367void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100368{
369 if( ctx == NULL )
370 return;
371
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100372#if defined(MBEDTLS_THREADING_C)
373 mbedtls_mutex_free( &ctx->mutex );
374#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200375 mbedtls_md_free( &ctx->md_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500376 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100377}
378
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200379#if defined(MBEDTLS_FS_IO)
380int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100381{
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100382 int ret;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100383 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200384 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100385
386 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200387 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100388
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200389 if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100390 goto exit;
391
392 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
393 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200394 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
Paul Bakker4c284c92014-03-26 15:33:05 +0100395 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100396 }
397
398 ret = 0;
399
400exit:
401 fclose( f );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500402 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100403
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100404 return( ret );
405}
406
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200407int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100408{
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100409 int ret = 0;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100410 FILE *f;
411 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200412 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100413
414 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200415 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100416
417 fseek( f, 0, SEEK_END );
418 n = (size_t) ftell( f );
419 fseek( f, 0, SEEK_SET );
420
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200421 if( n > MBEDTLS_HMAC_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100422 {
423 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200424 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100425 }
426
427 if( fread( buf, 1, n, f ) != n )
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100428 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
429 else
Gilles Peskine48dbe3b2018-09-13 22:19:57 +0200430 ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100431 fclose( f );
432
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500433 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100434
435 if( ret != 0 )
436 return( ret );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100437
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200438 return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100439}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200440#endif /* MBEDTLS_FS_IO */
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100441
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100442
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200443#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100444
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200445#if !defined(MBEDTLS_SHA1_C)
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100446/* Dummy checkup routine */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200447int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100448{
Manuel Pégourié-Gonnardd1004f02015-08-07 10:46:54 +0200449 (void) verbose;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100450 return( 0 );
451}
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100452#else
453
454#define OUTPUT_LEN 80
455
456/* From a NIST PR=true test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000457static const unsigned char entropy_pr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100458 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
459 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
460 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
461 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
462 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
463static const unsigned char result_pr[OUTPUT_LEN] = {
464 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
465 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
466 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
467 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
468 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
469 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
470 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
471
472/* From a NIST PR=false test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000473static const unsigned char entropy_nopr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100474 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
475 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
476 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
477 0xe9, 0x9d, 0xfe, 0xdf };
478static const unsigned char result_nopr[OUTPUT_LEN] = {
479 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
480 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
481 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
482 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
483 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
484 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
485 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
486
487/* "Entropy" from buffer */
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100488static size_t test_offset;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100489static int hmac_drbg_self_test_entropy( void *data,
490 unsigned char *buf, size_t len )
491{
492 const unsigned char *p = data;
493 memcpy( buf, p + test_offset, len );
494 test_offset += len;
495 return( 0 );
496}
497
Paul Bakker7dc4c442014-02-01 22:50:26 +0100498#define CHK( c ) if( (c) != 0 ) \
499 { \
500 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200501 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100502 return( 1 ); \
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100503 }
504
505/*
506 * Checkup routine for HMAC_DRBG with SHA-1
507 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200508int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100509{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200510 mbedtls_hmac_drbg_context ctx;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100511 unsigned char buf[OUTPUT_LEN];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200512 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100513
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200514 mbedtls_hmac_drbg_init( &ctx );
515
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100516 /*
517 * PR = True
518 */
519 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200520 mbedtls_printf( " HMAC_DRBG (PR = True) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100521
522 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200523 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000524 hmac_drbg_self_test_entropy, (void *) entropy_pr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100525 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200526 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
527 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
528 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100529 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200530 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100531
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100532 mbedtls_hmac_drbg_free( &ctx );
533
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100534 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200535 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100536
537 /*
538 * PR = False
539 */
540 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200541 mbedtls_printf( " HMAC_DRBG (PR = False) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100542
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100543 mbedtls_hmac_drbg_init( &ctx );
544
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100545 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200546 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000547 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100548 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200549 CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
550 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
551 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100552 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200553 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100554
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100555 mbedtls_hmac_drbg_free( &ctx );
556
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100557 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200558 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100559
560 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200561 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100562
563 return( 0 );
564}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200565#endif /* MBEDTLS_SHA1_C */
566#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100567
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200568#endif /* MBEDTLS_HMAC_DRBG_C */