blob: 73c606b99cff13edabce0e4f9e16be79b19021a9 [file] [log] [blame]
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +01001/*
2 * HMAC_DRBG implementation (NIST SP 800-90)
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010020 */
21
22/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010023 * The NIST SP 800-90A DRBGs are described in the following publication.
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010024 * http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010025 * References below are based on rev. 1 (January 2012).
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010026 */
27
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020028#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000029#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020030#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020031#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020032#endif
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010033
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020034#if defined(MBEDTLS_HMAC_DRBG_C)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010035
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000036#include "mbedtls/hmac_drbg.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050037#include "mbedtls/platform_util.h"
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010038
Rich Evans00ab4702015-02-06 13:43:58 +000039#include <string.h>
40
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#if defined(MBEDTLS_FS_IO)
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +010042#include <stdio.h>
43#endif
44
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020045#if defined(MBEDTLS_SELF_TEST)
46#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000047#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010048#else
Rich Evans00ab4702015-02-06 13:43:58 +000049#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020050#define mbedtls_printf printf
51#endif /* MBEDTLS_SELF_TEST */
52#endif /* MBEDTLS_PLATFORM_C */
Paul Bakker7dc4c442014-02-01 22:50:26 +010053
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010054/*
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +020055 * HMAC_DRBG context initialization
56 */
57void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx )
58{
59 memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010060
61#if defined(MBEDTLS_THREADING_C)
62 mbedtls_mutex_init( &ctx->mutex );
63#endif
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +020064}
65
66/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010067 * HMAC_DRBG update, using optional additional data (10.1.2.2)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010068 */
Gilles Peskine48dbe3b2018-09-13 22:19:57 +020069int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx,
70 const unsigned char *additional,
71 size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010072{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020073 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010074 unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
75 unsigned char sep[1];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020076 unsigned char K[MBEDTLS_MD_MAX_SIZE];
Gilles Peskine48dbe3b2018-09-13 22:19:57 +020077 int ret;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010078
79 for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
80 {
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010081 /* Step 1 or 4 */
Gilles Peskine48dbe3b2018-09-13 22:19:57 +020082 if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
83 goto exit;
84 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
85 ctx->V, md_len ) ) != 0 )
86 goto exit;
87 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
88 sep, 1 ) ) != 0 )
89 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010090 if( rounds == 2 )
Gilles Peskine48dbe3b2018-09-13 22:19:57 +020091 {
92 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
93 additional, add_len ) ) != 0 )
94 goto exit;
95 }
96 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, K ) ) != 0 )
97 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010098
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010099 /* Step 2 or 5 */
Gilles Peskine48dbe3b2018-09-13 22:19:57 +0200100 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ) ) != 0 )
101 goto exit;
102 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
103 ctx->V, md_len ) ) != 0 )
104 goto exit;
105 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
106 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100107 }
Gilles Peskinebae04832018-09-11 15:35:41 +0200108
Gilles Peskine48dbe3b2018-09-13 22:19:57 +0200109exit:
Gilles Peskinebae04832018-09-11 15:35:41 +0200110 mbedtls_platform_zeroize( K, sizeof( K ) );
Gilles Peskine48dbe3b2018-09-13 22:19:57 +0200111 return( ret );
112}
113
114void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
115 const unsigned char *additional,
116 size_t add_len )
117{
118 (void) mbedtls_hmac_drbg_update_ret( ctx, additional, add_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100119}
120
121/*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100122 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100123 */
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200124int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200125 const mbedtls_md_info_t * md_info,
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100126 const unsigned char *data, size_t data_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100127{
128 int ret;
129
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200130 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100131 return( ret );
132
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100133 /*
134 * Set initial working state.
135 * Use the V memory location, which is currently all 0, to initialize the
136 * MD context with an all-zero key. Then set V to its initial value.
137 */
Gilles Peskine808639b2018-09-11 16:54:57 +0200138 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V,
139 mbedtls_md_get_size( md_info ) ) ) != 0 )
140 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200141 memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100142
Gilles Peskine48dbe3b2018-09-13 22:19:57 +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 Peskine48dbe3b2018-09-13 22:19:57 +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 */
Gilles Peskine808639b2018-09-11 16:54:57 +0200169 if( ( ret = ctx->f_entropy( ctx->p_entropy,
170 seed, ctx->entropy_len ) ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200171 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100172
173 seedlen = ctx->entropy_len;
174
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100175 /* 1. Concatenate entropy and additional data if any */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100176 if( additional != NULL && len != 0 )
177 {
178 memcpy( seed + seedlen, additional, len );
179 seedlen += len;
180 }
181
182 /* 2. Update state */
Gilles Peskine48dbe3b2018-09-13 22:19:57 +0200183 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, seed, seedlen ) ) != 0 )
184 goto exit;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100185
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100186 /* 3. Reset reseed_counter */
187 ctx->reseed_counter = 1;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100188
Gilles Peskine48dbe3b2018-09-13 22:19:57 +0200189exit:
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100190 /* 4. Done */
Gilles Peskinebae04832018-09-11 15:35:41 +0200191 mbedtls_platform_zeroize( seed, seedlen );
Gilles Peskine48dbe3b2018-09-13 22:19:57 +0200192 return( ret );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100193}
194
195/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100196 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100197 */
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200198int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200199 const mbedtls_md_info_t * md_info,
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100200 int (*f_entropy)(void *, unsigned char *, size_t),
201 void *p_entropy,
202 const unsigned char *custom,
203 size_t len )
204{
205 int ret;
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100206 size_t entropy_len, md_size;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100207
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200208 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100209 return( ret );
210
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200211 md_size = mbedtls_md_get_size( md_info );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100212
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100213 /*
214 * Set initial working state.
215 * Use the V memory location, which is currently all 0, to initialize the
216 * MD context with an all-zero key. Then set V to its initial value.
217 */
Gilles Peskine808639b2018-09-11 16:54:57 +0200218 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ) ) != 0 )
219 return( ret );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100220 memset( ctx->V, 0x01, md_size );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100221
222 ctx->f_entropy = f_entropy;
223 ctx->p_entropy = p_entropy;
224
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200225 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100226
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100227 /*
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100228 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
229 * each hash function, then according to SP800-90A rev1 10.1 table 2,
230 * min_entropy_len (in bits) is security_strength.
231 *
232 * (This also matches the sizes used in the NIST test vectors.)
233 */
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100234 entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
235 md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
236 32; /* better (256+) -> 256 bits */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100237
238 /*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100239 * For initialisation, use more entropy to emulate a nonce
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100240 * (Again, matches test vectors.)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100241 */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100242 ctx->entropy_len = entropy_len * 3 / 2;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100243
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200244 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100245 return( ret );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100246
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100247 ctx->entropy_len = entropy_len;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100248
249 return( 0 );
250}
251
252/*
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100253 * Set prediction resistance
254 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200255void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100256 int resistance )
257{
258 ctx->prediction_resistance = resistance;
259}
260
261/*
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100262 * Set entropy length grabbed for reseeds
263 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200264void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100265{
266 ctx->entropy_len = len;
267}
268
269/*
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100270 * Set reseed interval
271 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200272void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval )
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100273{
274 ctx->reseed_interval = interval;
275}
276
277/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100278 * HMAC_DRBG random function with optional additional data:
279 * 10.1.2.5 (arabic) + 9.3 (Roman)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100280 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200281int mbedtls_hmac_drbg_random_with_add( void *p_rng,
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100282 unsigned char *output, size_t out_len,
283 const unsigned char *additional, size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100284{
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100285 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200286 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
287 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100288 size_t left = out_len;
289 unsigned char *out = output;
290
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100291 /* II. Check request length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200292 if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST )
293 return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100294
295 /* III. Check input length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200296 if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
297 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100298
299 /* 1. (aka VII and IX) Check reseed counter and PR */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100300 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200301 ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100302 ctx->reseed_counter > ctx->reseed_interval ) )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100303 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200304 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100305 return( ret );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100306
307 add_len = 0; /* VII.4 */
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100308 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100309
310 /* 2. Use additional data if any */
311 if( additional != NULL && add_len != 0 )
Gilles Peskine48dbe3b2018-09-13 22:19:57 +0200312 {
313 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
314 additional, add_len ) ) != 0 )
315 goto exit;
316 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100317
318 /* 3, 4, 5. Generate bytes */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100319 while( left != 0 )
320 {
321 size_t use_len = left > md_len ? md_len : left;
322
Gilles Peskine808639b2018-09-11 16:54:57 +0200323 if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
324 goto exit;
325 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
326 ctx->V, md_len ) ) != 0 )
327 goto exit;
328 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
329 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100330
331 memcpy( out, ctx->V, use_len );
332 out += use_len;
333 left -= use_len;
334 }
335
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100336 /* 6. Update */
Gilles Peskine48dbe3b2018-09-13 22:19:57 +0200337 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
338 additional, add_len ) ) != 0 )
339 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100340
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100341 /* 7. Update reseed counter */
342 ctx->reseed_counter++;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100343
Gilles Peskine48dbe3b2018-09-13 22:19:57 +0200344exit:
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100345 /* 8. Done */
Gilles Peskine48dbe3b2018-09-13 22:19:57 +0200346 return( ret );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100347}
348
349/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100350 * HMAC_DRBG random function
351 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200352int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100353{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100354 int ret;
355 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
356
357#if defined(MBEDTLS_THREADING_C)
358 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
359 return( ret );
360#endif
361
362 ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
363
364#if defined(MBEDTLS_THREADING_C)
365 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
366 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
367#endif
368
369 return( ret );
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100370}
371
372/*
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100373 * Free an HMAC_DRBG context
374 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200375void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100376{
377 if( ctx == NULL )
378 return;
379
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100380#if defined(MBEDTLS_THREADING_C)
381 mbedtls_mutex_free( &ctx->mutex );
382#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200383 mbedtls_md_free( &ctx->md_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500384 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100385}
386
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200387#if defined(MBEDTLS_FS_IO)
388int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100389{
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100390 int ret;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100391 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200392 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100393
394 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200395 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100396
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200397 if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100398 goto exit;
399
400 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
401 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200402 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
Paul Bakker4c284c92014-03-26 15:33:05 +0100403 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100404 }
405
406 ret = 0;
407
408exit:
409 fclose( f );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500410 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100411
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100412 return( ret );
413}
414
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200415int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100416{
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100417 int ret = 0;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100418 FILE *f;
419 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200420 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100421
422 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200423 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100424
425 fseek( f, 0, SEEK_END );
426 n = (size_t) ftell( f );
427 fseek( f, 0, SEEK_SET );
428
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200429 if( n > MBEDTLS_HMAC_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100430 {
431 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200432 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100433 }
434
435 if( fread( buf, 1, n, f ) != n )
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100436 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
437 else
Gilles Peskine48dbe3b2018-09-13 22:19:57 +0200438 ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n );
Gilles Peskine808639b2018-09-11 16:54:57 +0200439
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100440 fclose( f );
441
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500442 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100443
444 if( ret != 0 )
445 return( ret );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100446
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200447 return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100448}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449#endif /* MBEDTLS_FS_IO */
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100450
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100451
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200452#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100453
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200454#if !defined(MBEDTLS_SHA1_C)
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100455/* Dummy checkup routine */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200456int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100457{
Manuel Pégourié-Gonnardd1004f02015-08-07 10:46:54 +0200458 (void) verbose;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100459 return( 0 );
460}
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100461#else
462
463#define OUTPUT_LEN 80
464
465/* From a NIST PR=true test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000466static const unsigned char entropy_pr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100467 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
468 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
469 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
470 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
471 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
472static const unsigned char result_pr[OUTPUT_LEN] = {
473 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
474 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
475 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
476 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
477 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
478 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
479 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
480
481/* From a NIST PR=false test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000482static const unsigned char entropy_nopr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100483 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
484 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
485 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
486 0xe9, 0x9d, 0xfe, 0xdf };
487static const unsigned char result_nopr[OUTPUT_LEN] = {
488 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
489 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
490 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
491 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
492 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
493 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
494 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
495
496/* "Entropy" from buffer */
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100497static size_t test_offset;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100498static int hmac_drbg_self_test_entropy( void *data,
499 unsigned char *buf, size_t len )
500{
501 const unsigned char *p = data;
502 memcpy( buf, p + test_offset, len );
503 test_offset += len;
504 return( 0 );
505}
506
Paul Bakker7dc4c442014-02-01 22:50:26 +0100507#define CHK( c ) if( (c) != 0 ) \
508 { \
509 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200510 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100511 return( 1 ); \
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100512 }
513
514/*
515 * Checkup routine for HMAC_DRBG with SHA-1
516 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200517int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100518{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200519 mbedtls_hmac_drbg_context ctx;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100520 unsigned char buf[OUTPUT_LEN];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200521 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100522
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200523 mbedtls_hmac_drbg_init( &ctx );
524
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100525 /*
526 * PR = True
527 */
528 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200529 mbedtls_printf( " HMAC_DRBG (PR = True) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100530
531 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200532 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000533 hmac_drbg_self_test_entropy, (void *) entropy_pr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100534 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200535 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
536 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
537 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100538 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200539 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100540
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100541 mbedtls_hmac_drbg_free( &ctx );
542
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100543 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200544 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100545
546 /*
547 * PR = False
548 */
549 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200550 mbedtls_printf( " HMAC_DRBG (PR = False) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100551
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100552 mbedtls_hmac_drbg_init( &ctx );
553
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100554 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200555 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000556 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100557 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200558 CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
559 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
560 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100561 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200562 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100563
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100564 mbedtls_hmac_drbg_free( &ctx );
565
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100566 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200567 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100568
569 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200570 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100571
572 return( 0 );
573}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200574#endif /* MBEDTLS_SHA1_C */
575#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100576
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200577#endif /* MBEDTLS_HMAC_DRBG_C */