blob: 710eb84202e28becf2670e591327015d7b058df2 [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 ) );
65}
66
67/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010068 * HMAC_DRBG update, using optional additional data (10.1.2.2)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010069 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020070void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010071 const unsigned char *additional, size_t add_len )
72{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020073 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010074 unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
75 unsigned char sep[1];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020076 unsigned char K[MBEDTLS_MD_MAX_SIZE];
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010077
78 for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
79 {
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010080 /* Step 1 or 4 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020081 mbedtls_md_hmac_reset( &ctx->md_ctx );
82 mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
83 mbedtls_md_hmac_update( &ctx->md_ctx, sep, 1 );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010084 if( rounds == 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020085 mbedtls_md_hmac_update( &ctx->md_ctx, additional, add_len );
86 mbedtls_md_hmac_finish( &ctx->md_ctx, K );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010087
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010088 /* Step 2 or 5 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020089 mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len );
90 mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
91 mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010092 }
93}
94
95/*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +010096 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010097 */
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +020098int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020099 const mbedtls_md_info_t * md_info,
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100100 const unsigned char *data, size_t data_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100101{
102 int ret;
103
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200104 memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100105
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200106 mbedtls_md_init( &ctx->md_ctx );
Paul Bakker84bbeb52014-07-01 14:53:22 +0200107
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 memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100179
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200180 mbedtls_md_init( &ctx->md_ctx );
Paul Bakker84bbeb52014-07-01 14:53:22 +0200181
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200182 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100183 return( ret );
184
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200185 md_size = mbedtls_md_get_size( md_info );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100186
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100187 /*
188 * Set initial working state.
189 * Use the V memory location, which is currently all 0, to initialize the
190 * MD context with an all-zero key. Then set V to its initial value.
191 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200192 mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100193 memset( ctx->V, 0x01, md_size );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100194
195 ctx->f_entropy = f_entropy;
196 ctx->p_entropy = p_entropy;
197
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200198 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100199
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100200 /*
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100201 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
202 * each hash function, then according to SP800-90A rev1 10.1 table 2,
203 * min_entropy_len (in bits) is security_strength.
204 *
205 * (This also matches the sizes used in the NIST test vectors.)
206 */
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100207 entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
208 md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
209 32; /* better (256+) -> 256 bits */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100210
211 /*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100212 * For initialisation, use more entropy to emulate a nonce
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100213 * (Again, matches test vectors.)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100214 */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100215 ctx->entropy_len = entropy_len * 3 / 2;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100216
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200217 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100218 return( ret );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100219
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100220 ctx->entropy_len = entropy_len;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100221
222 return( 0 );
223}
224
225/*
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100226 * Set prediction resistance
227 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200228void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100229 int resistance )
230{
231 ctx->prediction_resistance = resistance;
232}
233
234/*
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100235 * Set entropy length grabbed for reseeds
236 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200237void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100238{
239 ctx->entropy_len = len;
240}
241
242/*
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100243 * Set reseed interval
244 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200245void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval )
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100246{
247 ctx->reseed_interval = interval;
248}
249
250/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100251 * HMAC_DRBG random function with optional additional data:
252 * 10.1.2.5 (arabic) + 9.3 (Roman)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100253 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200254int mbedtls_hmac_drbg_random_with_add( void *p_rng,
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100255 unsigned char *output, size_t out_len,
256 const unsigned char *additional, size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100257{
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100258 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200259 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
260 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100261 size_t left = out_len;
262 unsigned char *out = output;
263
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100264 /* II. Check request length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200265 if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST )
266 return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100267
268 /* III. Check input length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200269 if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
270 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100271
272 /* 1. (aka VII and IX) Check reseed counter and PR */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100273 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200274 ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100275 ctx->reseed_counter > ctx->reseed_interval ) )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100276 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200277 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100278 return( ret );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100279
280 add_len = 0; /* VII.4 */
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100281 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100282
283 /* 2. Use additional data if any */
284 if( additional != NULL && add_len != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200285 mbedtls_hmac_drbg_update( ctx, additional, add_len );
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100286
287 /* 3, 4, 5. Generate bytes */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100288 while( left != 0 )
289 {
290 size_t use_len = left > md_len ? md_len : left;
291
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200292 mbedtls_md_hmac_reset( &ctx->md_ctx );
293 mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
294 mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100295
296 memcpy( out, ctx->V, use_len );
297 out += use_len;
298 left -= use_len;
299 }
300
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100301 /* 6. Update */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200302 mbedtls_hmac_drbg_update( ctx, additional, add_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100303
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100304 /* 7. Update reseed counter */
305 ctx->reseed_counter++;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100306
307 /* 8. Done */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100308 return( 0 );
309}
310
311/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100312 * HMAC_DRBG random function
313 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200314int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100315{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200316 return( mbedtls_hmac_drbg_random_with_add( p_rng, output, out_len, NULL, 0 ) );
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100317}
318
319/*
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100320 * Free an HMAC_DRBG context
321 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200322void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100323{
324 if( ctx == NULL )
325 return;
326
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200327 mbedtls_md_free( &ctx->md_ctx );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100328
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200329 mbedtls_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100330}
331
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200332#if defined(MBEDTLS_FS_IO)
333int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100334{
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100335 int ret;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100336 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200337 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100338
339 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200340 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100341
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200342 if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100343 goto exit;
344
345 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
346 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200347 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
Paul Bakker4c284c92014-03-26 15:33:05 +0100348 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100349 }
350
351 ret = 0;
352
353exit:
354 fclose( f );
355 return( ret );
356}
357
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200358int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100359{
360 FILE *f;
361 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200362 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100363
364 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200365 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100366
367 fseek( f, 0, SEEK_END );
368 n = (size_t) ftell( f );
369 fseek( f, 0, SEEK_SET );
370
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200371 if( n > MBEDTLS_HMAC_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100372 {
373 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200374 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100375 }
376
377 if( fread( buf, 1, n, f ) != n )
378 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100379 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200380 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100381 }
382
383 fclose( f );
384
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200385 mbedtls_hmac_drbg_update( ctx, buf, n );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100386
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200387 return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100388}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200389#endif /* MBEDTLS_FS_IO */
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100390
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100391
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200392#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100393
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200394#if !defined(MBEDTLS_SHA1_C)
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100395/* Dummy checkup routine */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200396int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100397{
398
399 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200400 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100401
402 return( 0 );
403}
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100404#else
405
406#define OUTPUT_LEN 80
407
408/* From a NIST PR=true test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000409static const unsigned char entropy_pr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100410 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
411 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
412 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
413 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
414 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
415static const unsigned char result_pr[OUTPUT_LEN] = {
416 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
417 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
418 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
419 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
420 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
421 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
422 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
423
424/* From a NIST PR=false test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000425static const unsigned char entropy_nopr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100426 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
427 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
428 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
429 0xe9, 0x9d, 0xfe, 0xdf };
430static const unsigned char result_nopr[OUTPUT_LEN] = {
431 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
432 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
433 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
434 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
435 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
436 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
437 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
438
439/* "Entropy" from buffer */
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100440static size_t test_offset;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100441static int hmac_drbg_self_test_entropy( void *data,
442 unsigned char *buf, size_t len )
443{
444 const unsigned char *p = data;
445 memcpy( buf, p + test_offset, len );
446 test_offset += len;
447 return( 0 );
448}
449
Paul Bakker7dc4c442014-02-01 22:50:26 +0100450#define CHK( c ) if( (c) != 0 ) \
451 { \
452 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200453 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100454 return( 1 ); \
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100455 }
456
457/*
458 * Checkup routine for HMAC_DRBG with SHA-1
459 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200460int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100461{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462 mbedtls_hmac_drbg_context ctx;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100463 unsigned char buf[OUTPUT_LEN];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200464 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100465
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200466 mbedtls_hmac_drbg_init( &ctx );
467
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100468 /*
469 * PR = True
470 */
471 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200472 mbedtls_printf( " HMAC_DRBG (PR = True) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100473
474 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200475 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000476 hmac_drbg_self_test_entropy, (void *) entropy_pr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100477 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200478 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
479 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
480 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100481 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200482 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100483
484 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200485 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100486
487 /*
488 * PR = False
489 */
490 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200491 mbedtls_printf( " HMAC_DRBG (PR = False) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100492
493 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200494 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000495 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100496 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200497 CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
498 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
499 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100500 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200501 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100502
503 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200504 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100505
506 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200507 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100508
509 return( 0 );
510}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200511#endif /* MBEDTLS_SHA1_C */
512#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100513
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200514#endif /* MBEDTLS_HMAC_DRBG_C */