blob: c50330e7d8b9b91073f55eb39c401efba1e7ced8 [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 */
Gilles Peskineb7f71c82018-09-11 16:54:57 +0200140 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V,
141 mbedtls_md_get_size( md_info ) ) ) != 0 )
142 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200143 memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100144
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200145 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, data, data_len ) ) != 0 )
146 return( ret );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100147
148 return( 0 );
149}
150
151/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100152 * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100153 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200154int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100155 const unsigned char *additional, size_t len )
156{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200157 unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100158 size_t seedlen;
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200159 int ret;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100160
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100161 /* III. Check input length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200162 if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
163 ctx->entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100164 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200165 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100166 }
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100167
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200168 memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100169
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100170 /* IV. Gather entropy_len bytes of entropy for the seed */
Gilles Peskineb7f71c82018-09-11 16:54:57 +0200171 if( ( ret = ctx->f_entropy( ctx->p_entropy,
172 seed, ctx->entropy_len ) ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200173 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100174
175 seedlen = ctx->entropy_len;
176
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100177 /* 1. Concatenate entropy and additional data if any */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100178 if( additional != NULL && len != 0 )
179 {
180 memcpy( seed + seedlen, additional, len );
181 seedlen += len;
182 }
183
184 /* 2. Update state */
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200185 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, seed, seedlen ) ) != 0 )
186 goto exit;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100187
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100188 /* 3. Reset reseed_counter */
189 ctx->reseed_counter = 1;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100190
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200191exit:
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100192 /* 4. Done */
Gilles Peskineafa80372018-09-11 15:35:41 +0200193 mbedtls_platform_zeroize( seed, seedlen );
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200194 return( ret );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100195}
196
197/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100198 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100199 */
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200200int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200201 const mbedtls_md_info_t * md_info,
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100202 int (*f_entropy)(void *, unsigned char *, size_t),
203 void *p_entropy,
204 const unsigned char *custom,
205 size_t len )
206{
207 int ret;
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100208 size_t entropy_len, md_size;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100209
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200210 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100211 return( ret );
212
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200213 md_size = mbedtls_md_get_size( md_info );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100214
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100215 /*
216 * Set initial working state.
217 * Use the V memory location, which is currently all 0, to initialize the
218 * MD context with an all-zero key. Then set V to its initial value.
219 */
Gilles Peskineb7f71c82018-09-11 16:54:57 +0200220 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ) ) != 0 )
221 return( ret );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100222 memset( ctx->V, 0x01, md_size );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100223
224 ctx->f_entropy = f_entropy;
225 ctx->p_entropy = p_entropy;
226
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200227 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100228
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100229 /*
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100230 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
231 * each hash function, then according to SP800-90A rev1 10.1 table 2,
232 * min_entropy_len (in bits) is security_strength.
233 *
234 * (This also matches the sizes used in the NIST test vectors.)
235 */
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100236 entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
237 md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
238 32; /* better (256+) -> 256 bits */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100239
240 /*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100241 * For initialisation, use more entropy to emulate a nonce
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100242 * (Again, matches test vectors.)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100243 */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100244 ctx->entropy_len = entropy_len * 3 / 2;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100245
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200246 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100247 return( ret );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100248
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100249 ctx->entropy_len = entropy_len;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100250
251 return( 0 );
252}
253
254/*
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100255 * Set prediction resistance
256 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200257void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100258 int resistance )
259{
260 ctx->prediction_resistance = resistance;
261}
262
263/*
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100264 * Set entropy length grabbed for reseeds
265 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200266void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100267{
268 ctx->entropy_len = len;
269}
270
271/*
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100272 * Set reseed interval
273 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200274void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval )
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100275{
276 ctx->reseed_interval = interval;
277}
278
279/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100280 * HMAC_DRBG random function with optional additional data:
281 * 10.1.2.5 (arabic) + 9.3 (Roman)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100282 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200283int mbedtls_hmac_drbg_random_with_add( void *p_rng,
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100284 unsigned char *output, size_t out_len,
285 const unsigned char *additional, size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100286{
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100287 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200288 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
289 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100290 size_t left = out_len;
291 unsigned char *out = output;
292
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100293 /* II. Check request length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200294 if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST )
295 return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100296
297 /* III. Check input length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200298 if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
299 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100300
301 /* 1. (aka VII and IX) Check reseed counter and PR */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100302 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200303 ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100304 ctx->reseed_counter > ctx->reseed_interval ) )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100305 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200306 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100307 return( ret );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100308
309 add_len = 0; /* VII.4 */
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100310 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100311
312 /* 2. Use additional data if any */
313 if( additional != NULL && add_len != 0 )
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200314 {
315 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
316 additional, add_len ) ) != 0 )
317 goto exit;
318 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100319
320 /* 3, 4, 5. Generate bytes */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100321 while( left != 0 )
322 {
323 size_t use_len = left > md_len ? md_len : left;
324
Gilles Peskineb7f71c82018-09-11 16:54:57 +0200325 if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
326 goto exit;
327 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
328 ctx->V, md_len ) ) != 0 )
329 goto exit;
330 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
331 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100332
333 memcpy( out, ctx->V, use_len );
334 out += use_len;
335 left -= use_len;
336 }
337
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100338 /* 6. Update */
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200339 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
340 additional, add_len ) ) != 0 )
341 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100342
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100343 /* 7. Update reseed counter */
344 ctx->reseed_counter++;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100345
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200346exit:
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100347 /* 8. Done */
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200348 return( ret );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100349}
350
351/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100352 * HMAC_DRBG random function
353 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200354int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100355{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100356 int ret;
357 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
358
359#if defined(MBEDTLS_THREADING_C)
360 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
361 return( ret );
362#endif
363
364 ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
365
366#if defined(MBEDTLS_THREADING_C)
367 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
368 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
369#endif
370
371 return( ret );
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100372}
373
374/*
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100375 * Free an HMAC_DRBG context
376 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200377void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100378{
379 if( ctx == NULL )
380 return;
381
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100382#if defined(MBEDTLS_THREADING_C)
383 mbedtls_mutex_free( &ctx->mutex );
384#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200385 mbedtls_md_free( &ctx->md_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500386 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100387}
388
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200389#if defined(MBEDTLS_FS_IO)
390int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100391{
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100392 int ret;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100393 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200394 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100395
396 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200397 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100398
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200399 if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100400 goto exit;
401
402 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
403 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200404 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
Paul Bakker4c284c92014-03-26 15:33:05 +0100405 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100406 }
407
408 ret = 0;
409
410exit:
411 fclose( f );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500412 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100413
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100414 return( ret );
415}
416
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200417int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100418{
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100419 int ret = 0;
Gilles Peskine82204662018-09-11 18:43:09 +0200420 FILE *f = NULL;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100421 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200422 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Gilles Peskine82204662018-09-11 18:43:09 +0200423 unsigned char c;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100424
425 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200426 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100427
Gilles Peskine82204662018-09-11 18:43:09 +0200428 n = fread( buf, 1, sizeof( buf ), f );
429 if( fread( &c, 1, 1, f ) != 0 )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100430 {
Gilles Peskine82204662018-09-11 18:43:09 +0200431 ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
432 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100433 }
Gilles Peskine82204662018-09-11 18:43:09 +0200434 if( n == 0 || ferror( f ) )
435 {
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100436 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
Gilles Peskine82204662018-09-11 18:43:09 +0200437 goto exit;
438 }
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100439 fclose( f );
Gilles Peskine82204662018-09-11 18:43:09 +0200440 f = NULL;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100441
Gilles Peskine82204662018-09-11 18:43:09 +0200442 ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n );
443
444exit:
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500445 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Gilles Peskine82204662018-09-11 18:43:09 +0200446 if( f != NULL )
447 fclose( f );
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100448 if( ret != 0 )
449 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200450 return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100451}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200452#endif /* MBEDTLS_FS_IO */
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100453
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100454
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200455#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100456
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200457#if !defined(MBEDTLS_SHA1_C)
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100458/* Dummy checkup routine */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200459int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100460{
Manuel Pégourié-Gonnardd1004f02015-08-07 10:46:54 +0200461 (void) verbose;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100462 return( 0 );
463}
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100464#else
465
466#define OUTPUT_LEN 80
467
468/* From a NIST PR=true test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000469static const unsigned char entropy_pr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100470 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
471 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
472 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
473 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
474 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
475static const unsigned char result_pr[OUTPUT_LEN] = {
476 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
477 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
478 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
479 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
480 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
481 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
482 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
483
484/* From a NIST PR=false test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000485static const unsigned char entropy_nopr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100486 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
487 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
488 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
489 0xe9, 0x9d, 0xfe, 0xdf };
490static const unsigned char result_nopr[OUTPUT_LEN] = {
491 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
492 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
493 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
494 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
495 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
496 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
497 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
498
499/* "Entropy" from buffer */
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100500static size_t test_offset;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100501static int hmac_drbg_self_test_entropy( void *data,
502 unsigned char *buf, size_t len )
503{
504 const unsigned char *p = data;
505 memcpy( buf, p + test_offset, len );
506 test_offset += len;
507 return( 0 );
508}
509
Paul Bakker7dc4c442014-02-01 22:50:26 +0100510#define CHK( c ) if( (c) != 0 ) \
511 { \
512 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200513 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100514 return( 1 ); \
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100515 }
516
517/*
518 * Checkup routine for HMAC_DRBG with SHA-1
519 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200520int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100521{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200522 mbedtls_hmac_drbg_context ctx;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100523 unsigned char buf[OUTPUT_LEN];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200524 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100525
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200526 mbedtls_hmac_drbg_init( &ctx );
527
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100528 /*
529 * PR = True
530 */
531 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200532 mbedtls_printf( " HMAC_DRBG (PR = True) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100533
534 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200535 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000536 hmac_drbg_self_test_entropy, (void *) entropy_pr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100537 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200538 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
539 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
540 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100541 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200542 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100543
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100544 mbedtls_hmac_drbg_free( &ctx );
545
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100546 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200547 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100548
549 /*
550 * PR = False
551 */
552 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200553 mbedtls_printf( " HMAC_DRBG (PR = False) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100554
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100555 mbedtls_hmac_drbg_init( &ctx );
556
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100557 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200558 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000559 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100560 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200561 CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
562 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
563 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100564 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200565 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100566
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100567 mbedtls_hmac_drbg_free( &ctx );
568
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100569 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200570 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100571
572 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200573 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100574
575 return( 0 );
576}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200577#endif /* MBEDTLS_SHA1_C */
578#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100579
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200580#endif /* MBEDTLS_HMAC_DRBG_C */