blob: 5c4ee6def390248fff4973e11ca447f0fe8055e2 [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é-Gonnarda658a402015-01-23 09:45:19 +00004 * Copyright (C) 2014, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +01005 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +00006 * This file is part of mbed TLS (https://tls.mbed.org)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +01007 *
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +01008 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
23/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010024 * The NIST SP 800-90A DRBGs are described in the following publication.
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010025 * http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010026 * References below are based on rev. 1 (January 2012).
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010027 */
28
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020029#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000030#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020031#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020032#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020033#endif
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010034
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020035#if defined(MBEDTLS_HMAC_DRBG_C)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010036
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000037#include "mbedtls/hmac_drbg.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
Paul Bakker34617722014-06-13 17:20:13 +020054/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020055static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakker34617722014-06-13 17:20:13 +020056 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
57}
58
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010059/*
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +020060 * HMAC_DRBG context initialization
61 */
62void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx )
63{
64 memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010065
66#if defined(MBEDTLS_THREADING_C)
67 mbedtls_mutex_init( &ctx->mutex );
68#endif
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +020069}
70
71/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010072 * HMAC_DRBG update, using optional additional data (10.1.2.2)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010073 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020074void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010075 const unsigned char *additional, size_t add_len )
76{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020077 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010078 unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
79 unsigned char sep[1];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020080 unsigned char K[MBEDTLS_MD_MAX_SIZE];
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010081
82 for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
83 {
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010084 /* Step 1 or 4 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020085 mbedtls_md_hmac_reset( &ctx->md_ctx );
86 mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
87 mbedtls_md_hmac_update( &ctx->md_ctx, sep, 1 );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010088 if( rounds == 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020089 mbedtls_md_hmac_update( &ctx->md_ctx, additional, add_len );
90 mbedtls_md_hmac_finish( &ctx->md_ctx, K );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010091
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010092 /* Step 2 or 5 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020093 mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len );
94 mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
95 mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010096 }
97}
98
99/*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100100 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100101 */
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200102int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200103 const mbedtls_md_info_t * md_info,
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100104 const unsigned char *data, size_t data_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100105{
106 int ret;
107
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200108 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100109 return( ret );
110
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100111 /*
112 * Set initial working state.
113 * Use the V memory location, which is currently all 0, to initialize the
114 * MD context with an all-zero key. Then set V to its initial value.
115 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200116 mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, mbedtls_md_get_size( md_info ) );
117 memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100118
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200119 mbedtls_hmac_drbg_update( ctx, data, data_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100120
121 return( 0 );
122}
123
124/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100125 * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100126 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200127int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100128 const unsigned char *additional, size_t len )
129{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200130 unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100131 size_t seedlen;
132
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100133 /* III. Check input length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200134 if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
135 ctx->entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100136 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200137 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100138 }
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100139
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200140 memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100141
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100142 /* IV. Gather entropy_len bytes of entropy for the seed */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100143 if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200144 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100145
146 seedlen = ctx->entropy_len;
147
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100148 /* 1. Concatenate entropy and additional data if any */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100149 if( additional != NULL && len != 0 )
150 {
151 memcpy( seed + seedlen, additional, len );
152 seedlen += len;
153 }
154
155 /* 2. Update state */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200156 mbedtls_hmac_drbg_update( ctx, seed, seedlen );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100157
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100158 /* 3. Reset reseed_counter */
159 ctx->reseed_counter = 1;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100160
161 /* 4. Done */
162 return( 0 );
163}
164
165/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100166 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100167 */
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200168int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200169 const mbedtls_md_info_t * md_info,
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100170 int (*f_entropy)(void *, unsigned char *, size_t),
171 void *p_entropy,
172 const unsigned char *custom,
173 size_t len )
174{
175 int ret;
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100176 size_t entropy_len, md_size;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100177
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200178 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100179 return( ret );
180
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200181 md_size = mbedtls_md_get_size( md_info );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100182
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100183 /*
184 * Set initial working state.
185 * Use the V memory location, which is currently all 0, to initialize the
186 * MD context with an all-zero key. Then set V to its initial value.
187 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200188 mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100189 memset( ctx->V, 0x01, md_size );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100190
191 ctx->f_entropy = f_entropy;
192 ctx->p_entropy = p_entropy;
193
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200194 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100195
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100196 /*
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100197 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
198 * each hash function, then according to SP800-90A rev1 10.1 table 2,
199 * min_entropy_len (in bits) is security_strength.
200 *
201 * (This also matches the sizes used in the NIST test vectors.)
202 */
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100203 entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
204 md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
205 32; /* better (256+) -> 256 bits */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100206
207 /*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100208 * For initialisation, use more entropy to emulate a nonce
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100209 * (Again, matches test vectors.)
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 * 3 / 2;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100212
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200213 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100214 return( ret );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100215
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100216 ctx->entropy_len = entropy_len;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100217
218 return( 0 );
219}
220
221/*
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100222 * Set prediction resistance
223 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200224void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100225 int resistance )
226{
227 ctx->prediction_resistance = resistance;
228}
229
230/*
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100231 * Set entropy length grabbed for reseeds
232 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200233void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100234{
235 ctx->entropy_len = len;
236}
237
238/*
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100239 * Set reseed interval
240 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200241void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval )
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100242{
243 ctx->reseed_interval = interval;
244}
245
246/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100247 * HMAC_DRBG random function with optional additional data:
248 * 10.1.2.5 (arabic) + 9.3 (Roman)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100249 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200250int mbedtls_hmac_drbg_random_with_add( void *p_rng,
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100251 unsigned char *output, size_t out_len,
252 const unsigned char *additional, size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100253{
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100254 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200255 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
256 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100257 size_t left = out_len;
258 unsigned char *out = output;
259
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100260 /* II. Check request length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200261 if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST )
262 return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100263
264 /* III. Check input length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200265 if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
266 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100267
268 /* 1. (aka VII and IX) Check reseed counter and PR */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100269 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200270 ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100271 ctx->reseed_counter > ctx->reseed_interval ) )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100272 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200273 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100274 return( ret );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100275
276 add_len = 0; /* VII.4 */
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100277 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100278
279 /* 2. Use additional data if any */
280 if( additional != NULL && add_len != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200281 mbedtls_hmac_drbg_update( ctx, additional, add_len );
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100282
283 /* 3, 4, 5. Generate bytes */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100284 while( left != 0 )
285 {
286 size_t use_len = left > md_len ? md_len : left;
287
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200288 mbedtls_md_hmac_reset( &ctx->md_ctx );
289 mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
290 mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100291
292 memcpy( out, ctx->V, use_len );
293 out += use_len;
294 left -= use_len;
295 }
296
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100297 /* 6. Update */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200298 mbedtls_hmac_drbg_update( ctx, additional, add_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100299
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100300 /* 7. Update reseed counter */
301 ctx->reseed_counter++;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100302
303 /* 8. Done */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100304 return( 0 );
305}
306
307/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100308 * HMAC_DRBG random function
309 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200310int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100311{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100312 int ret;
313 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
314
315#if defined(MBEDTLS_THREADING_C)
316 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
317 return( ret );
318#endif
319
320 ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
321
322#if defined(MBEDTLS_THREADING_C)
323 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
324 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
325#endif
326
327 return( ret );
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100328}
329
330/*
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100331 * Free an HMAC_DRBG context
332 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200333void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100334{
335 if( ctx == NULL )
336 return;
337
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100338#if defined(MBEDTLS_THREADING_C)
339 mbedtls_mutex_free( &ctx->mutex );
340#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200341 mbedtls_md_free( &ctx->md_ctx );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200342 mbedtls_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100343}
344
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200345#if defined(MBEDTLS_FS_IO)
346int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100347{
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100348 int ret;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100349 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200350 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100351
352 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200353 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100354
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200355 if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100356 goto exit;
357
358 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
359 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200360 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
Paul Bakker4c284c92014-03-26 15:33:05 +0100361 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100362 }
363
364 ret = 0;
365
366exit:
367 fclose( f );
368 return( ret );
369}
370
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200371int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100372{
373 FILE *f;
374 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200375 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100376
377 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200378 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100379
380 fseek( f, 0, SEEK_END );
381 n = (size_t) ftell( f );
382 fseek( f, 0, SEEK_SET );
383
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200384 if( n > MBEDTLS_HMAC_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100385 {
386 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200387 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100388 }
389
390 if( fread( buf, 1, n, f ) != n )
391 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100392 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200393 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100394 }
395
396 fclose( f );
397
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200398 mbedtls_hmac_drbg_update( ctx, buf, n );
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{
411
412 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200413 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100414
415 return( 0 );
416}
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100417#else
418
419#define OUTPUT_LEN 80
420
421/* From a NIST PR=true test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000422static const unsigned char entropy_pr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100423 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
424 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
425 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
426 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
427 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
428static const unsigned char result_pr[OUTPUT_LEN] = {
429 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
430 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
431 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
432 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
433 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
434 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
435 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
436
437/* From a NIST PR=false test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000438static const unsigned char entropy_nopr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100439 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
440 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
441 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
442 0xe9, 0x9d, 0xfe, 0xdf };
443static const unsigned char result_nopr[OUTPUT_LEN] = {
444 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
445 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
446 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
447 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
448 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
449 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
450 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
451
452/* "Entropy" from buffer */
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100453static size_t test_offset;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100454static int hmac_drbg_self_test_entropy( void *data,
455 unsigned char *buf, size_t len )
456{
457 const unsigned char *p = data;
458 memcpy( buf, p + test_offset, len );
459 test_offset += len;
460 return( 0 );
461}
462
Paul Bakker7dc4c442014-02-01 22:50:26 +0100463#define CHK( c ) if( (c) != 0 ) \
464 { \
465 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200466 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100467 return( 1 ); \
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100468 }
469
470/*
471 * Checkup routine for HMAC_DRBG with SHA-1
472 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200473int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100474{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200475 mbedtls_hmac_drbg_context ctx;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100476 unsigned char buf[OUTPUT_LEN];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200477 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100478
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200479 mbedtls_hmac_drbg_init( &ctx );
480
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100481 /*
482 * PR = True
483 */
484 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200485 mbedtls_printf( " HMAC_DRBG (PR = True) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100486
487 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200488 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000489 hmac_drbg_self_test_entropy, (void *) entropy_pr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100490 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200491 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
492 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
493 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100494 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200495 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100496
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100497 mbedtls_hmac_drbg_free( &ctx );
498
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100499 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200500 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100501
502 /*
503 * PR = False
504 */
505 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200506 mbedtls_printf( " HMAC_DRBG (PR = False) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100507
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100508 mbedtls_hmac_drbg_init( &ctx );
509
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100510 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200511 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000512 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100513 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200514 CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
515 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
516 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100517 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200518 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100519
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100520 mbedtls_hmac_drbg_free( &ctx );
521
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100522 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200523 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100524
525 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200526 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100527
528 return( 0 );
529}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200530#endif /* MBEDTLS_SHA1_C */
531#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100532
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200533#endif /* MBEDTLS_HMAC_DRBG_C */