blob: 48d5b484169daa6d0264bc0e9e18d8c8347572ec [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é-Gonnard8208d162014-01-30 12:19:26 +010060 * HMAC_DRBG update, using optional additional data (10.1.2.2)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010061 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020062void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010063 const unsigned char *additional, size_t add_len )
64{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020065 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010066 unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
67 unsigned char sep[1];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020068 unsigned char K[MBEDTLS_MD_MAX_SIZE];
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010069
70 for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
71 {
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010072 /* Step 1 or 4 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020073 mbedtls_md_hmac_reset( &ctx->md_ctx );
74 mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
75 mbedtls_md_hmac_update( &ctx->md_ctx, sep, 1 );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010076 if( rounds == 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020077 mbedtls_md_hmac_update( &ctx->md_ctx, additional, add_len );
78 mbedtls_md_hmac_finish( &ctx->md_ctx, K );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010079
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010080 /* Step 2 or 5 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020081 mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len );
82 mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
83 mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010084 }
85}
86
87/*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +010088 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010089 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020090int mbedtls_hmac_drbg_init_buf( mbedtls_hmac_drbg_context *ctx,
91 const mbedtls_md_info_t * md_info,
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +010092 const unsigned char *data, size_t data_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010093{
94 int ret;
95
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020096 memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010097
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020098 mbedtls_md_init( &ctx->md_ctx );
Paul Bakker84bbeb52014-07-01 14:53:22 +020099
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200100 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100101 return( ret );
102
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100103 /*
104 * Set initial working state.
105 * Use the V memory location, which is currently all 0, to initialize the
106 * MD context with an all-zero key. Then set V to its initial value.
107 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200108 mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, mbedtls_md_get_size( md_info ) );
109 memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100110
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200111 mbedtls_hmac_drbg_update( ctx, data, data_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100112
113 return( 0 );
114}
115
116/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100117 * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100118 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200119int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100120 const unsigned char *additional, size_t len )
121{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200122 unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100123 size_t seedlen;
124
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100125 /* III. Check input length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200126 if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
127 ctx->entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100128 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200129 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100130 }
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100131
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200132 memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100133
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100134 /* IV. Gather entropy_len bytes of entropy for the seed */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100135 if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200136 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100137
138 seedlen = ctx->entropy_len;
139
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100140 /* 1. Concatenate entropy and additional data if any */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100141 if( additional != NULL && len != 0 )
142 {
143 memcpy( seed + seedlen, additional, len );
144 seedlen += len;
145 }
146
147 /* 2. Update state */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200148 mbedtls_hmac_drbg_update( ctx, seed, seedlen );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100149
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100150 /* 3. Reset reseed_counter */
151 ctx->reseed_counter = 1;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100152
153 /* 4. Done */
154 return( 0 );
155}
156
157/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100158 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100159 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200160int mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx,
161 const mbedtls_md_info_t * md_info,
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100162 int (*f_entropy)(void *, unsigned char *, size_t),
163 void *p_entropy,
164 const unsigned char *custom,
165 size_t len )
166{
167 int ret;
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100168 size_t entropy_len, md_size;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100169
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200170 memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100171
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200172 mbedtls_md_init( &ctx->md_ctx );
Paul Bakker84bbeb52014-07-01 14:53:22 +0200173
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200174 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100175 return( ret );
176
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200177 md_size = mbedtls_md_get_size( md_info );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100178
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100179 /*
180 * Set initial working state.
181 * Use the V memory location, which is currently all 0, to initialize the
182 * MD context with an all-zero key. Then set V to its initial value.
183 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200184 mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100185 memset( ctx->V, 0x01, md_size );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100186
187 ctx->f_entropy = f_entropy;
188 ctx->p_entropy = p_entropy;
189
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200190 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100191
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100192 /*
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100193 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
194 * each hash function, then according to SP800-90A rev1 10.1 table 2,
195 * min_entropy_len (in bits) is security_strength.
196 *
197 * (This also matches the sizes used in the NIST test vectors.)
198 */
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100199 entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
200 md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
201 32; /* better (256+) -> 256 bits */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100202
203 /*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100204 * For initialisation, use more entropy to emulate a nonce
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100205 * (Again, matches test vectors.)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100206 */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100207 ctx->entropy_len = entropy_len * 3 / 2;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100208
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200209 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100210 return( ret );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100211
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100212 ctx->entropy_len = entropy_len;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100213
214 return( 0 );
215}
216
217/*
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100218 * Set prediction resistance
219 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200220void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100221 int resistance )
222{
223 ctx->prediction_resistance = resistance;
224}
225
226/*
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100227 * Set entropy length grabbed for reseeds
228 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200229void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100230{
231 ctx->entropy_len = len;
232}
233
234/*
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100235 * Set reseed interval
236 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200237void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval )
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100238{
239 ctx->reseed_interval = interval;
240}
241
242/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100243 * HMAC_DRBG random function with optional additional data:
244 * 10.1.2.5 (arabic) + 9.3 (Roman)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100245 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200246int mbedtls_hmac_drbg_random_with_add( void *p_rng,
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100247 unsigned char *output, size_t out_len,
248 const unsigned char *additional, size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100249{
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100250 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200251 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
252 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100253 size_t left = out_len;
254 unsigned char *out = output;
255
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100256 /* II. Check request length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200257 if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST )
258 return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100259
260 /* III. Check input length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200261 if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
262 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100263
264 /* 1. (aka VII and IX) Check reseed counter and PR */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100265 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200266 ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100267 ctx->reseed_counter > ctx->reseed_interval ) )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100268 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200269 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100270 return( ret );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100271
272 add_len = 0; /* VII.4 */
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100273 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100274
275 /* 2. Use additional data if any */
276 if( additional != NULL && add_len != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200277 mbedtls_hmac_drbg_update( ctx, additional, add_len );
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100278
279 /* 3, 4, 5. Generate bytes */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100280 while( left != 0 )
281 {
282 size_t use_len = left > md_len ? md_len : left;
283
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200284 mbedtls_md_hmac_reset( &ctx->md_ctx );
285 mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
286 mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100287
288 memcpy( out, ctx->V, use_len );
289 out += use_len;
290 left -= use_len;
291 }
292
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100293 /* 6. Update */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200294 mbedtls_hmac_drbg_update( ctx, additional, add_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100295
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100296 /* 7. Update reseed counter */
297 ctx->reseed_counter++;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100298
299 /* 8. Done */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100300 return( 0 );
301}
302
303/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100304 * HMAC_DRBG random function
305 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200306int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100307{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200308 return( mbedtls_hmac_drbg_random_with_add( p_rng, output, out_len, NULL, 0 ) );
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100309}
310
311/*
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100312 * Free an HMAC_DRBG context
313 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200314void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100315{
316 if( ctx == NULL )
317 return;
318
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200319 mbedtls_md_free( &ctx->md_ctx );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100320
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200321 mbedtls_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100322}
323
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200324#if defined(MBEDTLS_FS_IO)
325int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100326{
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100327 int ret;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100328 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200329 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100330
331 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200332 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100333
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200334 if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100335 goto exit;
336
337 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
338 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200339 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
Paul Bakker4c284c92014-03-26 15:33:05 +0100340 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100341 }
342
343 ret = 0;
344
345exit:
346 fclose( f );
347 return( ret );
348}
349
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200350int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100351{
352 FILE *f;
353 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200354 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100355
356 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200357 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100358
359 fseek( f, 0, SEEK_END );
360 n = (size_t) ftell( f );
361 fseek( f, 0, SEEK_SET );
362
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200363 if( n > MBEDTLS_HMAC_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100364 {
365 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200366 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100367 }
368
369 if( fread( buf, 1, n, f ) != n )
370 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100371 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200372 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100373 }
374
375 fclose( f );
376
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200377 mbedtls_hmac_drbg_update( ctx, buf, n );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100378
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200379 return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100380}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200381#endif /* MBEDTLS_FS_IO */
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100382
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100383
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200384#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100385
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200386#if !defined(MBEDTLS_SHA1_C)
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100387/* Dummy checkup routine */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200388int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100389{
390
391 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200392 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100393
394 return( 0 );
395}
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100396#else
397
398#define OUTPUT_LEN 80
399
400/* From a NIST PR=true test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000401static const unsigned char entropy_pr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100402 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
403 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
404 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
405 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
406 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
407static const unsigned char result_pr[OUTPUT_LEN] = {
408 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
409 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
410 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
411 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
412 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
413 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
414 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
415
416/* From a NIST PR=false test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000417static const unsigned char entropy_nopr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100418 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
419 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
420 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
421 0xe9, 0x9d, 0xfe, 0xdf };
422static const unsigned char result_nopr[OUTPUT_LEN] = {
423 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
424 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
425 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
426 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
427 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
428 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
429 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
430
431/* "Entropy" from buffer */
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100432static size_t test_offset;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100433static int hmac_drbg_self_test_entropy( void *data,
434 unsigned char *buf, size_t len )
435{
436 const unsigned char *p = data;
437 memcpy( buf, p + test_offset, len );
438 test_offset += len;
439 return( 0 );
440}
441
Paul Bakker7dc4c442014-02-01 22:50:26 +0100442#define CHK( c ) if( (c) != 0 ) \
443 { \
444 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200445 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100446 return( 1 ); \
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100447 }
448
449/*
450 * Checkup routine for HMAC_DRBG with SHA-1
451 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200452int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100453{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200454 mbedtls_hmac_drbg_context ctx;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100455 unsigned char buf[OUTPUT_LEN];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200456 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100457
458 /*
459 * PR = True
460 */
461 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462 mbedtls_printf( " HMAC_DRBG (PR = True) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100463
464 test_offset = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200465 CHK( mbedtls_hmac_drbg_init( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000466 hmac_drbg_self_test_entropy, (void *) entropy_pr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100467 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200468 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
469 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
470 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100471 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200472 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100473
474 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200475 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100476
477 /*
478 * PR = False
479 */
480 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 mbedtls_printf( " HMAC_DRBG (PR = False) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100482
483 test_offset = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200484 CHK( mbedtls_hmac_drbg_init( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000485 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100486 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200487 CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
488 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
489 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100490 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200491 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100492
493 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200494 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100495
496 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200497 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100498
499 return( 0 );
500}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200501#endif /* MBEDTLS_SHA1_C */
502#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100503
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200504#endif /* MBEDTLS_HMAC_DRBG_C */