blob: 7f653547750eeb9a2aee30264ef4806a00217a63 [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 Peskinee0e9c572018-09-11 16:47:16 +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 Peskinee0e9c572018-09-11 16:47:16 +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 Peskinee0e9c572018-09-11 16:47:16 +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 Peskinee0e9c572018-09-11 16:47:16 +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 Peskinee0e9c572018-09-11 16:47:16 +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 Peskineafa80372018-09-11 15:35:41 +0200108
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200109exit:
Gilles Peskineafa80372018-09-11 15:35:41 +0200110 mbedtls_platform_zeroize( K, sizeof( K ) );
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200111 return( ret );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100112}
113
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200114#if !defined(MBEDTLS_DEPRECATED_REMOVED)
115void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
116 const unsigned char *additional,
117 size_t add_len )
118{
119 (void) mbedtls_hmac_drbg_update_ret( ctx, additional, add_len );
120}
121#endif /* MBEDTLS_DEPRECATED_REMOVED */
122
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100123/*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100124 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100125 */
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200126int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200127 const mbedtls_md_info_t * md_info,
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100128 const unsigned char *data, size_t data_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100129{
130 int ret;
131
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200132 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100133 return( ret );
134
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100135 /*
136 * Set initial working state.
137 * Use the V memory location, which is currently all 0, to initialize the
138 * MD context with an all-zero key. Then set V to its initial value.
139 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200140 mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, mbedtls_md_get_size( md_info ) );
141 memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100142
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200143 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, data, data_len ) ) != 0 )
144 return( ret );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100145
146 return( 0 );
147}
148
149/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100150 * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100151 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200152int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100153 const unsigned char *additional, size_t len )
154{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200155 unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100156 size_t seedlen;
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200157 int ret;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100158
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100159 /* III. Check input length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200160 if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
161 ctx->entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100162 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200163 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100164 }
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100165
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200166 memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100167
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100168 /* IV. Gather entropy_len bytes of entropy for the seed */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100169 if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200170 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100171
172 seedlen = ctx->entropy_len;
173
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100174 /* 1. Concatenate entropy and additional data if any */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100175 if( additional != NULL && len != 0 )
176 {
177 memcpy( seed + seedlen, additional, len );
178 seedlen += len;
179 }
180
181 /* 2. Update state */
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200182 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, seed, seedlen ) ) != 0 )
183 goto exit;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100184
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100185 /* 3. Reset reseed_counter */
186 ctx->reseed_counter = 1;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100187
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200188exit:
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100189 /* 4. Done */
Gilles Peskineafa80372018-09-11 15:35:41 +0200190 mbedtls_platform_zeroize( seed, seedlen );
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200191 return( ret );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100192}
193
194/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100195 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100196 */
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200197int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200198 const mbedtls_md_info_t * md_info,
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100199 int (*f_entropy)(void *, unsigned char *, size_t),
200 void *p_entropy,
201 const unsigned char *custom,
202 size_t len )
203{
204 int ret;
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100205 size_t entropy_len, md_size;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100206
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200207 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100208 return( ret );
209
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200210 md_size = mbedtls_md_get_size( md_info );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100211
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100212 /*
213 * Set initial working state.
214 * Use the V memory location, which is currently all 0, to initialize the
215 * MD context with an all-zero key. Then set V to its initial value.
216 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200217 mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100218 memset( ctx->V, 0x01, md_size );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100219
220 ctx->f_entropy = f_entropy;
221 ctx->p_entropy = p_entropy;
222
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200223 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100224
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100225 /*
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100226 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
227 * each hash function, then according to SP800-90A rev1 10.1 table 2,
228 * min_entropy_len (in bits) is security_strength.
229 *
230 * (This also matches the sizes used in the NIST test vectors.)
231 */
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100232 entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
233 md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
234 32; /* better (256+) -> 256 bits */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100235
236 /*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100237 * For initialisation, use more entropy to emulate a nonce
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100238 * (Again, matches test vectors.)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100239 */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100240 ctx->entropy_len = entropy_len * 3 / 2;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100241
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200242 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100243 return( ret );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100244
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100245 ctx->entropy_len = entropy_len;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100246
247 return( 0 );
248}
249
250/*
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100251 * Set prediction resistance
252 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200253void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100254 int resistance )
255{
256 ctx->prediction_resistance = resistance;
257}
258
259/*
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100260 * Set entropy length grabbed for reseeds
261 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200262void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100263{
264 ctx->entropy_len = len;
265}
266
267/*
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100268 * Set reseed interval
269 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200270void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval )
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100271{
272 ctx->reseed_interval = interval;
273}
274
275/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100276 * HMAC_DRBG random function with optional additional data:
277 * 10.1.2.5 (arabic) + 9.3 (Roman)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100278 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200279int mbedtls_hmac_drbg_random_with_add( void *p_rng,
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100280 unsigned char *output, size_t out_len,
281 const unsigned char *additional, size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100282{
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100283 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200284 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
285 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100286 size_t left = out_len;
287 unsigned char *out = output;
288
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100289 /* II. Check request length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200290 if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST )
291 return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100292
293 /* III. Check input length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200294 if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
295 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100296
297 /* 1. (aka VII and IX) Check reseed counter and PR */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100298 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200299 ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100300 ctx->reseed_counter > ctx->reseed_interval ) )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100301 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200302 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100303 return( ret );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100304
305 add_len = 0; /* VII.4 */
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100306 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100307
308 /* 2. Use additional data if any */
309 if( additional != NULL && add_len != 0 )
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200310 {
311 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
312 additional, add_len ) ) != 0 )
313 goto exit;
314 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100315
316 /* 3, 4, 5. Generate bytes */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100317 while( left != 0 )
318 {
319 size_t use_len = left > md_len ? md_len : left;
320
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200321 mbedtls_md_hmac_reset( &ctx->md_ctx );
322 mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
323 mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100324
325 memcpy( out, ctx->V, use_len );
326 out += use_len;
327 left -= use_len;
328 }
329
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100330 /* 6. Update */
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200331 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
332 additional, add_len ) ) != 0 )
333 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100334
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100335 /* 7. Update reseed counter */
336 ctx->reseed_counter++;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100337
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200338exit:
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100339 /* 8. Done */
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200340 return( ret );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100341}
342
343/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100344 * HMAC_DRBG random function
345 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200346int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100347{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100348 int ret;
349 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
350
351#if defined(MBEDTLS_THREADING_C)
352 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
353 return( ret );
354#endif
355
356 ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
357
358#if defined(MBEDTLS_THREADING_C)
359 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
360 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
361#endif
362
363 return( ret );
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100364}
365
366/*
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100367 * Free an HMAC_DRBG context
368 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200369void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100370{
371 if( ctx == NULL )
372 return;
373
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100374#if defined(MBEDTLS_THREADING_C)
375 mbedtls_mutex_free( &ctx->mutex );
376#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200377 mbedtls_md_free( &ctx->md_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500378 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100379}
380
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200381#if defined(MBEDTLS_FS_IO)
382int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100383{
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100384 int ret;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100385 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200386 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100387
388 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200389 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100390
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200391 if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100392 goto exit;
393
394 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
395 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200396 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
Paul Bakker4c284c92014-03-26 15:33:05 +0100397 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100398 }
399
400 ret = 0;
401
402exit:
403 fclose( f );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500404 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100405
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100406 return( ret );
407}
408
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200409int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100410{
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100411 int ret = 0;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100412 FILE *f;
413 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200414 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100415
416 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200417 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100418
419 fseek( f, 0, SEEK_END );
420 n = (size_t) ftell( f );
421 fseek( f, 0, SEEK_SET );
422
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200423 if( n > MBEDTLS_HMAC_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100424 {
425 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200426 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100427 }
428
429 if( fread( buf, 1, n, f ) != n )
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100430 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
431 else
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200432 ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100433 fclose( f );
434
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500435 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100436
437 if( ret != 0 )
438 return( ret );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100439
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200440 return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100441}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200442#endif /* MBEDTLS_FS_IO */
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100443
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100444
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200445#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100446
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200447#if !defined(MBEDTLS_SHA1_C)
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100448/* Dummy checkup routine */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100450{
Manuel Pégourié-Gonnardd1004f02015-08-07 10:46:54 +0200451 (void) verbose;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100452 return( 0 );
453}
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100454#else
455
456#define OUTPUT_LEN 80
457
458/* From a NIST PR=true test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000459static const unsigned char entropy_pr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100460 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
461 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
462 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
463 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
464 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
465static const unsigned char result_pr[OUTPUT_LEN] = {
466 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
467 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
468 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
469 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
470 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
471 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
472 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
473
474/* From a NIST PR=false test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000475static const unsigned char entropy_nopr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100476 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
477 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
478 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
479 0xe9, 0x9d, 0xfe, 0xdf };
480static const unsigned char result_nopr[OUTPUT_LEN] = {
481 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
482 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
483 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
484 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
485 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
486 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
487 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
488
489/* "Entropy" from buffer */
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100490static size_t test_offset;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100491static int hmac_drbg_self_test_entropy( void *data,
492 unsigned char *buf, size_t len )
493{
494 const unsigned char *p = data;
495 memcpy( buf, p + test_offset, len );
496 test_offset += len;
497 return( 0 );
498}
499
Paul Bakker7dc4c442014-02-01 22:50:26 +0100500#define CHK( c ) if( (c) != 0 ) \
501 { \
502 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200503 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100504 return( 1 ); \
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100505 }
506
507/*
508 * Checkup routine for HMAC_DRBG with SHA-1
509 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200510int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100511{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200512 mbedtls_hmac_drbg_context ctx;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100513 unsigned char buf[OUTPUT_LEN];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200514 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100515
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200516 mbedtls_hmac_drbg_init( &ctx );
517
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100518 /*
519 * PR = True
520 */
521 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200522 mbedtls_printf( " HMAC_DRBG (PR = True) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100523
524 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200525 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000526 hmac_drbg_self_test_entropy, (void *) entropy_pr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100527 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200528 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
529 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
530 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100531 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200532 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100533
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100534 mbedtls_hmac_drbg_free( &ctx );
535
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100536 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200537 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100538
539 /*
540 * PR = False
541 */
542 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200543 mbedtls_printf( " HMAC_DRBG (PR = False) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100544
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100545 mbedtls_hmac_drbg_init( &ctx );
546
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100547 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200548 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000549 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100550 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200551 CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
552 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
553 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100554 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200555 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100556
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100557 mbedtls_hmac_drbg_free( &ctx );
558
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100559 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200560 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100561
562 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200563 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100564
565 return( 0 );
566}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200567#endif /* MBEDTLS_SHA1_C */
568#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100569
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200570#endif /* MBEDTLS_HMAC_DRBG_C */