blob: d5ac2f6ad0b27ed7e4c7ea67cf421fec4ecd2704 [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;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100420 FILE *f;
421 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200422 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100423
424 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200425 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100426
427 fseek( f, 0, SEEK_END );
428 n = (size_t) ftell( f );
429 fseek( f, 0, SEEK_SET );
430
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200431 if( n > MBEDTLS_HMAC_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100432 {
433 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200434 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100435 }
436
437 if( fread( buf, 1, n, f ) != n )
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100438 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
439 else
Gilles Peskinee0e9c572018-09-11 16:47:16 +0200440 ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n );
Gilles Peskineb7f71c82018-09-11 16:54:57 +0200441
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100442 fclose( f );
443
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500444 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100445
446 if( ret != 0 )
447 return( ret );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100448
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449 return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100450}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200451#endif /* MBEDTLS_FS_IO */
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100452
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100453
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200454#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100455
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200456#if !defined(MBEDTLS_SHA1_C)
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100457/* Dummy checkup routine */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200458int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100459{
Manuel Pégourié-Gonnardd1004f02015-08-07 10:46:54 +0200460 (void) verbose;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100461 return( 0 );
462}
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100463#else
464
465#define OUTPUT_LEN 80
466
467/* From a NIST PR=true test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000468static const unsigned char entropy_pr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100469 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
470 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
471 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
472 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
473 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
474static const unsigned char result_pr[OUTPUT_LEN] = {
475 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
476 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
477 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
478 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
479 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
480 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
481 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
482
483/* From a NIST PR=false test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000484static const unsigned char entropy_nopr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100485 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
486 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
487 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
488 0xe9, 0x9d, 0xfe, 0xdf };
489static const unsigned char result_nopr[OUTPUT_LEN] = {
490 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
491 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
492 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
493 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
494 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
495 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
496 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
497
498/* "Entropy" from buffer */
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100499static size_t test_offset;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100500static int hmac_drbg_self_test_entropy( void *data,
501 unsigned char *buf, size_t len )
502{
503 const unsigned char *p = data;
504 memcpy( buf, p + test_offset, len );
505 test_offset += len;
506 return( 0 );
507}
508
Paul Bakker7dc4c442014-02-01 22:50:26 +0100509#define CHK( c ) if( (c) != 0 ) \
510 { \
511 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200512 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100513 return( 1 ); \
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100514 }
515
516/*
517 * Checkup routine for HMAC_DRBG with SHA-1
518 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200519int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100520{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200521 mbedtls_hmac_drbg_context ctx;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100522 unsigned char buf[OUTPUT_LEN];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200523 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100524
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200525 mbedtls_hmac_drbg_init( &ctx );
526
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100527 /*
528 * PR = True
529 */
530 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200531 mbedtls_printf( " HMAC_DRBG (PR = True) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100532
533 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200534 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000535 hmac_drbg_self_test_entropy, (void *) entropy_pr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100536 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200537 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
538 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
539 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100540 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200541 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100542
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100543 mbedtls_hmac_drbg_free( &ctx );
544
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100545 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200546 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100547
548 /*
549 * PR = False
550 */
551 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200552 mbedtls_printf( " HMAC_DRBG (PR = False) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100553
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100554 mbedtls_hmac_drbg_init( &ctx );
555
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100556 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200557 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000558 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100559 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200560 CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
561 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
562 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100563 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200564 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100565
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100566 mbedtls_hmac_drbg_free( &ctx );
567
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100568 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200569 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100570
571 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200572 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100573
574 return( 0 );
575}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200576#endif /* MBEDTLS_SHA1_C */
577#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100578
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200579#endif /* MBEDTLS_HMAC_DRBG_C */