blob: dad55ff86163538e95e40e1859523ec81620be18 [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 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020069void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010070 const unsigned char *additional, size_t add_len )
71{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020072 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010073 unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
74 unsigned char sep[1];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020075 unsigned char K[MBEDTLS_MD_MAX_SIZE];
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010076
77 for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
78 {
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010079 /* Step 1 or 4 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020080 mbedtls_md_hmac_reset( &ctx->md_ctx );
81 mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
82 mbedtls_md_hmac_update( &ctx->md_ctx, sep, 1 );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010083 if( rounds == 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020084 mbedtls_md_hmac_update( &ctx->md_ctx, additional, add_len );
85 mbedtls_md_hmac_finish( &ctx->md_ctx, K );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010086
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010087 /* Step 2 or 5 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020088 mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len );
89 mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
90 mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010091 }
92}
93
94/*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +010095 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010096 */
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +020097int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020098 const mbedtls_md_info_t * md_info,
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +010099 const unsigned char *data, size_t data_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100100{
101 int ret;
102
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200103 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100104 return( ret );
105
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100106 /*
107 * Set initial working state.
108 * Use the V memory location, which is currently all 0, to initialize the
109 * MD context with an all-zero key. Then set V to its initial value.
110 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200111 mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, mbedtls_md_get_size( md_info ) );
112 memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100113
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200114 mbedtls_hmac_drbg_update( ctx, data, data_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100115
116 return( 0 );
117}
118
119/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100120 * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100121 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200122int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100123 const unsigned char *additional, size_t len )
124{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200125 unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100126 size_t seedlen;
127
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100128 /* III. Check input length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200129 if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
130 ctx->entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100131 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200132 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100133 }
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100134
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200135 memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100136
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100137 /* IV. Gather entropy_len bytes of entropy for the seed */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100138 if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200139 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100140
141 seedlen = ctx->entropy_len;
142
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100143 /* 1. Concatenate entropy and additional data if any */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100144 if( additional != NULL && len != 0 )
145 {
146 memcpy( seed + seedlen, additional, len );
147 seedlen += len;
148 }
149
150 /* 2. Update state */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200151 mbedtls_hmac_drbg_update( ctx, seed, seedlen );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100152
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100153 /* 3. Reset reseed_counter */
154 ctx->reseed_counter = 1;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100155
156 /* 4. Done */
157 return( 0 );
158}
159
160/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100161 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100162 */
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200163int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200164 const mbedtls_md_info_t * md_info,
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100165 int (*f_entropy)(void *, unsigned char *, size_t),
166 void *p_entropy,
167 const unsigned char *custom,
168 size_t len )
169{
170 int ret;
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100171 size_t entropy_len, md_size;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100172
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200173 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100174 return( ret );
175
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200176 md_size = mbedtls_md_get_size( md_info );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100177
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100178 /*
179 * Set initial working state.
180 * Use the V memory location, which is currently all 0, to initialize the
181 * MD context with an all-zero key. Then set V to its initial value.
182 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200183 mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100184 memset( ctx->V, 0x01, md_size );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100185
186 ctx->f_entropy = f_entropy;
187 ctx->p_entropy = p_entropy;
188
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200189 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100190
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100191 /*
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100192 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
193 * each hash function, then according to SP800-90A rev1 10.1 table 2,
194 * min_entropy_len (in bits) is security_strength.
195 *
196 * (This also matches the sizes used in the NIST test vectors.)
197 */
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100198 entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
199 md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
200 32; /* better (256+) -> 256 bits */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100201
202 /*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100203 * For initialisation, use more entropy to emulate a nonce
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100204 * (Again, matches test vectors.)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100205 */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100206 ctx->entropy_len = entropy_len * 3 / 2;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100207
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200208 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100209 return( ret );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100210
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100211 ctx->entropy_len = entropy_len;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100212
213 return( 0 );
214}
215
216/*
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100217 * Set prediction resistance
218 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200219void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100220 int resistance )
221{
222 ctx->prediction_resistance = resistance;
223}
224
225/*
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100226 * Set entropy length grabbed for reseeds
227 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200228void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100229{
230 ctx->entropy_len = len;
231}
232
233/*
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100234 * Set reseed interval
235 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200236void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval )
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100237{
238 ctx->reseed_interval = interval;
239}
240
241/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100242 * HMAC_DRBG random function with optional additional data:
243 * 10.1.2.5 (arabic) + 9.3 (Roman)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100244 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200245int mbedtls_hmac_drbg_random_with_add( void *p_rng,
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100246 unsigned char *output, size_t out_len,
247 const unsigned char *additional, size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100248{
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100249 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200250 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
251 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100252 size_t left = out_len;
253 unsigned char *out = output;
254
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100255 /* II. Check request length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200256 if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST )
257 return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100258
259 /* III. Check input length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200260 if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
261 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100262
263 /* 1. (aka VII and IX) Check reseed counter and PR */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100264 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200265 ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100266 ctx->reseed_counter > ctx->reseed_interval ) )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100267 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200268 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100269 return( ret );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100270
271 add_len = 0; /* VII.4 */
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100272 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100273
274 /* 2. Use additional data if any */
275 if( additional != NULL && add_len != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200276 mbedtls_hmac_drbg_update( ctx, additional, add_len );
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100277
278 /* 3, 4, 5. Generate bytes */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100279 while( left != 0 )
280 {
281 size_t use_len = left > md_len ? md_len : left;
282
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200283 mbedtls_md_hmac_reset( &ctx->md_ctx );
284 mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
285 mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100286
287 memcpy( out, ctx->V, use_len );
288 out += use_len;
289 left -= use_len;
290 }
291
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100292 /* 6. Update */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200293 mbedtls_hmac_drbg_update( ctx, additional, add_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100294
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100295 /* 7. Update reseed counter */
296 ctx->reseed_counter++;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100297
298 /* 8. Done */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100299 return( 0 );
300}
301
302/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100303 * HMAC_DRBG random function
304 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200305int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100306{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100307 int ret;
308 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
309
310#if defined(MBEDTLS_THREADING_C)
311 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
312 return( ret );
313#endif
314
315 ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
316
317#if defined(MBEDTLS_THREADING_C)
318 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
319 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
320#endif
321
322 return( ret );
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100323}
324
325/*
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100326 * Free an HMAC_DRBG context
327 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200328void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100329{
330 if( ctx == NULL )
331 return;
332
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100333#if defined(MBEDTLS_THREADING_C)
334 mbedtls_mutex_free( &ctx->mutex );
335#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200336 mbedtls_md_free( &ctx->md_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500337 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100338}
339
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200340#if defined(MBEDTLS_FS_IO)
341int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100342{
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100343 int ret;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100344 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200345 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100346
347 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200348 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100349
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200350 if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100351 goto exit;
352
353 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
354 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200355 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
Paul Bakker4c284c92014-03-26 15:33:05 +0100356 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100357 }
358
359 ret = 0;
360
361exit:
362 fclose( f );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500363 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100364
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100365 return( ret );
366}
367
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200368int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100369{
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100370 int ret = 0;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100371 FILE *f;
372 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200373 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100374
375 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200376 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100377
378 fseek( f, 0, SEEK_END );
379 n = (size_t) ftell( f );
380 fseek( f, 0, SEEK_SET );
381
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200382 if( n > MBEDTLS_HMAC_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100383 {
384 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200385 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100386 }
387
388 if( fread( buf, 1, n, f ) != n )
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100389 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
390 else
391 mbedtls_hmac_drbg_update( ctx, buf, n );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100392
393 fclose( f );
394
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500395 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100396
397 if( ret != 0 )
398 return( ret );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100399
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200400 return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100401}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200402#endif /* MBEDTLS_FS_IO */
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100403
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100404
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200405#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100406
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200407#if !defined(MBEDTLS_SHA1_C)
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100408/* Dummy checkup routine */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200409int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100410{
Manuel Pégourié-Gonnardd1004f02015-08-07 10:46:54 +0200411 (void) verbose;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100412 return( 0 );
413}
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100414#else
415
416#define OUTPUT_LEN 80
417
418/* From a NIST PR=true test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000419static const unsigned char entropy_pr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100420 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
421 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
422 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
423 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
424 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
425static const unsigned char result_pr[OUTPUT_LEN] = {
426 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
427 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
428 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
429 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
430 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
431 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
432 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
433
434/* From a NIST PR=false test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000435static const unsigned char entropy_nopr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100436 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
437 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
438 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
439 0xe9, 0x9d, 0xfe, 0xdf };
440static const unsigned char result_nopr[OUTPUT_LEN] = {
441 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
442 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
443 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
444 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
445 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
446 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
447 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
448
449/* "Entropy" from buffer */
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100450static size_t test_offset;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100451static int hmac_drbg_self_test_entropy( void *data,
452 unsigned char *buf, size_t len )
453{
454 const unsigned char *p = data;
455 memcpy( buf, p + test_offset, len );
456 test_offset += len;
457 return( 0 );
458}
459
Paul Bakker7dc4c442014-02-01 22:50:26 +0100460#define CHK( c ) if( (c) != 0 ) \
461 { \
462 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200463 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100464 return( 1 ); \
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100465 }
466
467/*
468 * Checkup routine for HMAC_DRBG with SHA-1
469 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200470int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100471{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200472 mbedtls_hmac_drbg_context ctx;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100473 unsigned char buf[OUTPUT_LEN];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200474 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100475
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200476 mbedtls_hmac_drbg_init( &ctx );
477
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100478 /*
479 * PR = True
480 */
481 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200482 mbedtls_printf( " HMAC_DRBG (PR = True) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100483
484 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200485 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000486 hmac_drbg_self_test_entropy, (void *) entropy_pr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100487 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200488 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
489 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
490 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100491 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200492 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100493
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100494 mbedtls_hmac_drbg_free( &ctx );
495
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100496 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200497 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100498
499 /*
500 * PR = False
501 */
502 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200503 mbedtls_printf( " HMAC_DRBG (PR = False) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100504
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100505 mbedtls_hmac_drbg_init( &ctx );
506
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100507 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200508 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000509 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100510 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200511 CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
512 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
513 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100514 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200515 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100516
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100517 mbedtls_hmac_drbg_free( &ctx );
518
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100519 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200520 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100521
522 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200523 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100524
525 return( 0 );
526}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200527#endif /* MBEDTLS_SHA1_C */
528#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100529
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200530#endif /* MBEDTLS_HMAC_DRBG_C */