blob: 02fcc7d00fb5c8aa7bcb1dee70ef07d528dc2d25 [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 memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100109
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200110 mbedtls_md_init( &ctx->md_ctx );
Paul Bakker84bbeb52014-07-01 14:53:22 +0200111
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200112 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100113 return( ret );
114
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100115 /*
116 * Set initial working state.
117 * Use the V memory location, which is currently all 0, to initialize the
118 * MD context with an all-zero key. Then set V to its initial value.
119 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200120 mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, mbedtls_md_get_size( md_info ) );
121 memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100122
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200123 mbedtls_hmac_drbg_update( ctx, data, data_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100124
125 return( 0 );
126}
127
128/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100129 * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100130 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200131int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100132 const unsigned char *additional, size_t len )
133{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200134 unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100135 size_t seedlen;
136
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100137 /* III. Check input length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200138 if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
139 ctx->entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100140 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200141 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100142 }
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100143
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200144 memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100145
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100146 /* IV. Gather entropy_len bytes of entropy for the seed */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100147 if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200148 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100149
150 seedlen = ctx->entropy_len;
151
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100152 /* 1. Concatenate entropy and additional data if any */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100153 if( additional != NULL && len != 0 )
154 {
155 memcpy( seed + seedlen, additional, len );
156 seedlen += len;
157 }
158
159 /* 2. Update state */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200160 mbedtls_hmac_drbg_update( ctx, seed, seedlen );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100161
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100162 /* 3. Reset reseed_counter */
163 ctx->reseed_counter = 1;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100164
165 /* 4. Done */
166 return( 0 );
167}
168
169/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100170 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100171 */
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200172int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200173 const mbedtls_md_info_t * md_info,
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100174 int (*f_entropy)(void *, unsigned char *, size_t),
175 void *p_entropy,
176 const unsigned char *custom,
177 size_t len )
178{
179 int ret;
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100180 size_t entropy_len, md_size;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100181
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200182 memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100183
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200184 mbedtls_md_init( &ctx->md_ctx );
Paul Bakker84bbeb52014-07-01 14:53:22 +0200185
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200186 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100187 return( ret );
188
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200189 md_size = mbedtls_md_get_size( md_info );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100190
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100191 /*
192 * Set initial working state.
193 * Use the V memory location, which is currently all 0, to initialize the
194 * MD context with an all-zero key. Then set V to its initial value.
195 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200196 mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100197 memset( ctx->V, 0x01, md_size );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100198
199 ctx->f_entropy = f_entropy;
200 ctx->p_entropy = p_entropy;
201
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200202 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100203
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100204 /*
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100205 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
206 * each hash function, then according to SP800-90A rev1 10.1 table 2,
207 * min_entropy_len (in bits) is security_strength.
208 *
209 * (This also matches the sizes used in the NIST test vectors.)
210 */
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100211 entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
212 md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
213 32; /* better (256+) -> 256 bits */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100214
215 /*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100216 * For initialisation, use more entropy to emulate a nonce
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100217 * (Again, matches test vectors.)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100218 */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100219 ctx->entropy_len = entropy_len * 3 / 2;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100220
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200221 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100222 return( ret );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100223
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100224 ctx->entropy_len = entropy_len;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100225
226 return( 0 );
227}
228
229/*
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100230 * Set prediction resistance
231 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200232void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100233 int resistance )
234{
235 ctx->prediction_resistance = resistance;
236}
237
238/*
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100239 * Set entropy length grabbed for reseeds
240 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200241void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100242{
243 ctx->entropy_len = len;
244}
245
246/*
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100247 * Set reseed interval
248 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200249void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval )
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100250{
251 ctx->reseed_interval = interval;
252}
253
254/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100255 * HMAC_DRBG random function with optional additional data:
256 * 10.1.2.5 (arabic) + 9.3 (Roman)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100257 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200258int mbedtls_hmac_drbg_random_with_add( void *p_rng,
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100259 unsigned char *output, size_t out_len,
260 const unsigned char *additional, size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100261{
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100262 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200263 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
264 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100265 size_t left = out_len;
266 unsigned char *out = output;
267
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100268 /* II. Check request length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200269 if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST )
270 return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100271
272 /* III. Check input length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200273 if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
274 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100275
276 /* 1. (aka VII and IX) Check reseed counter and PR */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100277 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200278 ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100279 ctx->reseed_counter > ctx->reseed_interval ) )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100280 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200281 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100282 return( ret );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100283
284 add_len = 0; /* VII.4 */
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100285 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100286
287 /* 2. Use additional data if any */
288 if( additional != NULL && add_len != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200289 mbedtls_hmac_drbg_update( ctx, additional, add_len );
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100290
291 /* 3, 4, 5. Generate bytes */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100292 while( left != 0 )
293 {
294 size_t use_len = left > md_len ? md_len : left;
295
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200296 mbedtls_md_hmac_reset( &ctx->md_ctx );
297 mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
298 mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100299
300 memcpy( out, ctx->V, use_len );
301 out += use_len;
302 left -= use_len;
303 }
304
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100305 /* 6. Update */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200306 mbedtls_hmac_drbg_update( ctx, additional, add_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100307
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100308 /* 7. Update reseed counter */
309 ctx->reseed_counter++;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100310
311 /* 8. Done */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100312 return( 0 );
313}
314
315/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100316 * HMAC_DRBG random function
317 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200318int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100319{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100320 int ret;
321 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
322
323#if defined(MBEDTLS_THREADING_C)
324 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
325 return( ret );
326#endif
327
328 ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
329
330#if defined(MBEDTLS_THREADING_C)
331 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
332 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
333#endif
334
335 return( ret );
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100336}
337
338/*
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100339 * Free an HMAC_DRBG context
340 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200341void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100342{
343 if( ctx == NULL )
344 return;
345
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100346#if defined(MBEDTLS_THREADING_C)
347 mbedtls_mutex_free( &ctx->mutex );
348#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200349 mbedtls_md_free( &ctx->md_ctx );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200350 mbedtls_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100351}
352
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200353#if defined(MBEDTLS_FS_IO)
354int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100355{
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100356 int ret;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100357 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200358 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100359
360 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200361 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100362
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200363 if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100364 goto exit;
365
366 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
367 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200368 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
Paul Bakker4c284c92014-03-26 15:33:05 +0100369 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100370 }
371
372 ret = 0;
373
374exit:
375 fclose( f );
376 return( ret );
377}
378
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200379int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100380{
381 FILE *f;
382 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200383 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100384
385 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200386 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100387
388 fseek( f, 0, SEEK_END );
389 n = (size_t) ftell( f );
390 fseek( f, 0, SEEK_SET );
391
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200392 if( n > MBEDTLS_HMAC_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100393 {
394 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200395 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100396 }
397
398 if( fread( buf, 1, n, f ) != n )
399 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100400 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200401 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100402 }
403
404 fclose( f );
405
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200406 mbedtls_hmac_drbg_update( ctx, buf, n );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100407
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200408 return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100409}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200410#endif /* MBEDTLS_FS_IO */
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100411
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100412
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200413#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100414
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200415#if !defined(MBEDTLS_SHA1_C)
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100416/* Dummy checkup routine */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200417int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100418{
419
420 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200421 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100422
423 return( 0 );
424}
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100425#else
426
427#define OUTPUT_LEN 80
428
429/* From a NIST PR=true test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000430static const unsigned char entropy_pr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100431 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
432 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
433 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
434 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
435 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
436static const unsigned char result_pr[OUTPUT_LEN] = {
437 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
438 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
439 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
440 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
441 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
442 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
443 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
444
445/* From a NIST PR=false test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000446static const unsigned char entropy_nopr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100447 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
448 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
449 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
450 0xe9, 0x9d, 0xfe, 0xdf };
451static const unsigned char result_nopr[OUTPUT_LEN] = {
452 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
453 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
454 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
455 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
456 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
457 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
458 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
459
460/* "Entropy" from buffer */
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100461static size_t test_offset;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100462static int hmac_drbg_self_test_entropy( void *data,
463 unsigned char *buf, size_t len )
464{
465 const unsigned char *p = data;
466 memcpy( buf, p + test_offset, len );
467 test_offset += len;
468 return( 0 );
469}
470
Paul Bakker7dc4c442014-02-01 22:50:26 +0100471#define CHK( c ) if( (c) != 0 ) \
472 { \
473 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200474 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100475 return( 1 ); \
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100476 }
477
478/*
479 * Checkup routine for HMAC_DRBG with SHA-1
480 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100482{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200483 mbedtls_hmac_drbg_context ctx;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100484 unsigned char buf[OUTPUT_LEN];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200485 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100486
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200487 mbedtls_hmac_drbg_init( &ctx );
488
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100489 /*
490 * PR = True
491 */
492 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200493 mbedtls_printf( " HMAC_DRBG (PR = True) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100494
495 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200496 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000497 hmac_drbg_self_test_entropy, (void *) entropy_pr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100498 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200499 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
500 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
501 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100502 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200503 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100504
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100505 mbedtls_hmac_drbg_free( &ctx );
506
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100507 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200508 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100509
510 /*
511 * PR = False
512 */
513 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200514 mbedtls_printf( " HMAC_DRBG (PR = False) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100515
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100516 mbedtls_hmac_drbg_init( &ctx );
517
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100518 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200519 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000520 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100521 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200522 CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
523 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
524 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100525 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200526 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100527
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100528 mbedtls_hmac_drbg_free( &ctx );
529
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100530 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200531 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100532
533 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200534 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100535
536 return( 0 );
537}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200538#endif /* MBEDTLS_SHA1_C */
539#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100540
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200541#endif /* MBEDTLS_HMAC_DRBG_C */