blob: 65c8daccd819873db7a03be3c7963a28783539bd [file] [log] [blame]
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +01001/*
2 * HMAC_DRBG implementation (NIST SP 800-90)
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010020 */
21
22/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010023 * The NIST SP 800-90A DRBGs are described in the following publication.
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010024 * http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010025 * References below are based on rev. 1 (January 2012).
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010026 */
27
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020028#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000029#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020030#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020031#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020032#endif
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010033
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020034#if defined(MBEDTLS_HMAC_DRBG_C)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010035
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000036#include "mbedtls/hmac_drbg.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050037#include "mbedtls/platform_util.h"
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010038
Rich Evans00ab4702015-02-06 13:43:58 +000039#include <string.h>
40
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#if defined(MBEDTLS_FS_IO)
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +010042#include <stdio.h>
43#endif
44
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020045#if defined(MBEDTLS_SELF_TEST)
46#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000047#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010048#else
Rich Evans00ab4702015-02-06 13:43:58 +000049#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020050#define mbedtls_printf printf
51#endif /* MBEDTLS_SELF_TEST */
52#endif /* MBEDTLS_PLATFORM_C */
Paul Bakker7dc4c442014-02-01 22:50:26 +010053
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010054/*
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +020055 * HMAC_DRBG context initialization
56 */
57void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx )
58{
59 memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010060
61#if defined(MBEDTLS_THREADING_C)
62 mbedtls_mutex_init( &ctx->mutex );
63#endif
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +020064}
65
66/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010067 * HMAC_DRBG update, using optional additional data (10.1.2.2)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010068 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020069void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010070 const unsigned char *additional, size_t add_len )
71{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020072 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010073 unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
74 unsigned char sep[1];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020075 unsigned char K[MBEDTLS_MD_MAX_SIZE];
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010076
77 for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
78 {
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010079 /* Step 1 or 4 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020080 mbedtls_md_hmac_reset( &ctx->md_ctx );
81 mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
82 mbedtls_md_hmac_update( &ctx->md_ctx, sep, 1 );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010083 if( rounds == 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020084 mbedtls_md_hmac_update( &ctx->md_ctx, additional, add_len );
85 mbedtls_md_hmac_finish( &ctx->md_ctx, K );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010086
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010087 /* Step 2 or 5 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020088 mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len );
89 mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
90 mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010091 }
Gilles Peskineafa80372018-09-11 15:35:41 +020092
93 mbedtls_platform_zeroize( K, sizeof( K ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010094}
95
96/*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +010097 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010098 */
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +020099int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200100 const mbedtls_md_info_t * md_info,
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100101 const unsigned char *data, size_t data_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100102{
103 int ret;
104
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200105 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100106 return( ret );
107
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100108 /*
109 * Set initial working state.
110 * Use the V memory location, which is currently all 0, to initialize the
111 * MD context with an all-zero key. Then set V to its initial value.
112 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200113 mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, mbedtls_md_get_size( md_info ) );
114 memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100115
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200116 mbedtls_hmac_drbg_update( ctx, data, data_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100117
118 return( 0 );
119}
120
121/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100122 * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100123 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200124int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100125 const unsigned char *additional, size_t len )
126{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200127 unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100128 size_t seedlen;
129
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100130 /* III. Check input length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200131 if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
132 ctx->entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100133 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200134 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100135 }
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100136
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200137 memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100138
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100139 /* IV. Gather entropy_len bytes of entropy for the seed */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100140 if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200141 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100142
143 seedlen = ctx->entropy_len;
144
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100145 /* 1. Concatenate entropy and additional data if any */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100146 if( additional != NULL && len != 0 )
147 {
148 memcpy( seed + seedlen, additional, len );
149 seedlen += len;
150 }
151
152 /* 2. Update state */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200153 mbedtls_hmac_drbg_update( ctx, seed, seedlen );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100154
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100155 /* 3. Reset reseed_counter */
156 ctx->reseed_counter = 1;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100157
158 /* 4. Done */
Gilles Peskineafa80372018-09-11 15:35:41 +0200159 mbedtls_platform_zeroize( seed, seedlen );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100160 return( 0 );
161}
162
163/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100164 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100165 */
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200166int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200167 const mbedtls_md_info_t * md_info,
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100168 int (*f_entropy)(void *, unsigned char *, size_t),
169 void *p_entropy,
170 const unsigned char *custom,
171 size_t len )
172{
173 int ret;
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100174 size_t entropy_len, md_size;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100175
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200176 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100177 return( ret );
178
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200179 md_size = mbedtls_md_get_size( md_info );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100180
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100181 /*
182 * Set initial working state.
183 * Use the V memory location, which is currently all 0, to initialize the
184 * MD context with an all-zero key. Then set V to its initial value.
185 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200186 mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100187 memset( ctx->V, 0x01, md_size );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100188
189 ctx->f_entropy = f_entropy;
190 ctx->p_entropy = p_entropy;
191
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200192 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100193
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100194 /*
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100195 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
196 * each hash function, then according to SP800-90A rev1 10.1 table 2,
197 * min_entropy_len (in bits) is security_strength.
198 *
199 * (This also matches the sizes used in the NIST test vectors.)
200 */
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100201 entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
202 md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
203 32; /* better (256+) -> 256 bits */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100204
205 /*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100206 * For initialisation, use more entropy to emulate a nonce
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100207 * (Again, matches test vectors.)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100208 */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100209 ctx->entropy_len = entropy_len * 3 / 2;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100210
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200211 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100212 return( ret );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100213
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100214 ctx->entropy_len = entropy_len;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100215
216 return( 0 );
217}
218
219/*
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100220 * Set prediction resistance
221 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200222void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100223 int resistance )
224{
225 ctx->prediction_resistance = resistance;
226}
227
228/*
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100229 * Set entropy length grabbed for reseeds
230 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200231void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100232{
233 ctx->entropy_len = len;
234}
235
236/*
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100237 * Set reseed interval
238 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200239void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval )
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100240{
241 ctx->reseed_interval = interval;
242}
243
244/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100245 * HMAC_DRBG random function with optional additional data:
246 * 10.1.2.5 (arabic) + 9.3 (Roman)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100247 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200248int mbedtls_hmac_drbg_random_with_add( void *p_rng,
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100249 unsigned char *output, size_t out_len,
250 const unsigned char *additional, size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100251{
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100252 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200253 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
254 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100255 size_t left = out_len;
256 unsigned char *out = output;
257
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100258 /* II. Check request length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200259 if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST )
260 return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100261
262 /* III. Check input length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200263 if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
264 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100265
266 /* 1. (aka VII and IX) Check reseed counter and PR */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100267 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200268 ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100269 ctx->reseed_counter > ctx->reseed_interval ) )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100270 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200271 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100272 return( ret );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100273
274 add_len = 0; /* VII.4 */
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100275 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100276
277 /* 2. Use additional data if any */
278 if( additional != NULL && add_len != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200279 mbedtls_hmac_drbg_update( ctx, additional, add_len );
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100280
281 /* 3, 4, 5. Generate bytes */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100282 while( left != 0 )
283 {
284 size_t use_len = left > md_len ? md_len : left;
285
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200286 mbedtls_md_hmac_reset( &ctx->md_ctx );
287 mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
288 mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100289
290 memcpy( out, ctx->V, use_len );
291 out += use_len;
292 left -= use_len;
293 }
294
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100295 /* 6. Update */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200296 mbedtls_hmac_drbg_update( ctx, additional, add_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100297
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100298 /* 7. Update reseed counter */
299 ctx->reseed_counter++;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100300
301 /* 8. Done */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100302 return( 0 );
303}
304
305/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100306 * HMAC_DRBG random function
307 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200308int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100309{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100310 int ret;
311 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
312
313#if defined(MBEDTLS_THREADING_C)
314 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
315 return( ret );
316#endif
317
318 ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
319
320#if defined(MBEDTLS_THREADING_C)
321 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
322 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
323#endif
324
325 return( ret );
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100326}
327
328/*
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100329 * Free an HMAC_DRBG context
330 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200331void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100332{
333 if( ctx == NULL )
334 return;
335
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100336#if defined(MBEDTLS_THREADING_C)
337 mbedtls_mutex_free( &ctx->mutex );
338#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200339 mbedtls_md_free( &ctx->md_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500340 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100341}
342
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200343#if defined(MBEDTLS_FS_IO)
344int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100345{
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100346 int ret;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100347 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200348 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100349
350 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200351 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100352
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200353 if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100354 goto exit;
355
356 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
357 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200358 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
Paul Bakker4c284c92014-03-26 15:33:05 +0100359 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100360 }
361
362 ret = 0;
363
364exit:
365 fclose( f );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500366 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100367
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100368 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{
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100373 int ret = 0;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100374 FILE *f;
375 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200376 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100377
378 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200379 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100380
381 fseek( f, 0, SEEK_END );
382 n = (size_t) ftell( f );
383 fseek( f, 0, SEEK_SET );
384
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200385 if( n > MBEDTLS_HMAC_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100386 {
387 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200388 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100389 }
390
391 if( fread( buf, 1, n, f ) != n )
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100392 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
393 else
394 mbedtls_hmac_drbg_update( ctx, buf, n );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100395
396 fclose( f );
397
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500398 mbedtls_platform_zeroize( buf, sizeof( buf ) );
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100399
400 if( ret != 0 )
401 return( ret );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100402
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200403 return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100404}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200405#endif /* MBEDTLS_FS_IO */
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100406
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100407
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200408#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100409
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200410#if !defined(MBEDTLS_SHA1_C)
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100411/* Dummy checkup routine */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200412int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100413{
Manuel Pégourié-Gonnardd1004f02015-08-07 10:46:54 +0200414 (void) verbose;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100415 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 */