blob: 11cf2de0df952757fbc1acbbab9baf2f9c0591ba [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"
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010037
Rich Evans00ab4702015-02-06 13:43:58 +000038#include <string.h>
39
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020040#if defined(MBEDTLS_FS_IO)
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +010041#include <stdio.h>
42#endif
43
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if defined(MBEDTLS_SELF_TEST)
45#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010047#else
Rich Evans00ab4702015-02-06 13:43:58 +000048#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020049#define mbedtls_printf printf
50#endif /* MBEDTLS_SELF_TEST */
51#endif /* MBEDTLS_PLATFORM_C */
Paul Bakker7dc4c442014-02-01 22:50:26 +010052
Paul Bakker34617722014-06-13 17:20:13 +020053/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020054static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakker34617722014-06-13 17:20:13 +020055 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
56}
57
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010058/*
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +020059 * HMAC_DRBG context initialization
60 */
61void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx )
62{
63 memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +010064
65#if defined(MBEDTLS_THREADING_C)
66 mbedtls_mutex_init( &ctx->mutex );
67#endif
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +020068}
69
70/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010071 * HMAC_DRBG update, using optional additional data (10.1.2.2)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010072 */
Gilles Peskine4d237572018-09-13 22:19:57 +020073int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx,
74 const unsigned char *additional,
75 size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010076{
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];
Gilles Peskine4d237572018-09-13 22:19:57 +020081 int ret;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010082
83 for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
84 {
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010085 /* Step 1 or 4 */
Gilles Peskine4d237572018-09-13 22:19:57 +020086 if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
87 goto exit;
88 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
89 ctx->V, md_len ) ) != 0 )
90 goto exit;
91 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
92 sep, 1 ) ) != 0 )
93 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010094 if( rounds == 2 )
Gilles Peskine4d237572018-09-13 22:19:57 +020095 {
96 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
97 additional, add_len ) ) != 0 )
98 goto exit;
99 }
100 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, K ) ) != 0 )
101 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100102
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100103 /* Step 2 or 5 */
Gilles Peskine4d237572018-09-13 22:19:57 +0200104 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ) ) != 0 )
105 goto exit;
106 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
107 ctx->V, md_len ) ) != 0 )
108 goto exit;
109 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
110 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100111 }
Gilles Peskine1da77762018-09-11 15:35:41 +0200112
Gilles Peskine4d237572018-09-13 22:19:57 +0200113exit:
Gilles Peskine1da77762018-09-11 15:35:41 +0200114 mbedtls_zeroize( K, sizeof( K ) );
Gilles Peskine4d237572018-09-13 22:19:57 +0200115 return( ret );
116}
117
118void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
119 const unsigned char *additional,
120 size_t add_len )
121{
122 (void) mbedtls_hmac_drbg_update_ret( ctx, additional, add_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100123}
124
125/*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100126 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100127 */
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200128int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200129 const mbedtls_md_info_t * md_info,
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100130 const unsigned char *data, size_t data_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100131{
132 int ret;
133
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200134 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100135 return( ret );
136
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100137 /*
138 * Set initial working state.
139 * Use the V memory location, which is currently all 0, to initialize the
140 * MD context with an all-zero key. Then set V to its initial value.
141 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200142 mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, mbedtls_md_get_size( md_info ) );
143 memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100144
Gilles Peskine4d237572018-09-13 22:19:57 +0200145 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, data, data_len ) ) != 0 )
146 return( ret );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100147
148 return( 0 );
149}
150
151/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100152 * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100153 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200154int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100155 const unsigned char *additional, size_t len )
156{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200157 unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100158 size_t seedlen;
Gilles Peskine4d237572018-09-13 22:19:57 +0200159 int ret;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100160
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100161 /* III. Check input length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200162 if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
163 ctx->entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100164 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200165 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100166 }
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100167
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200168 memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100169
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100170 /* IV. Gather entropy_len bytes of entropy for the seed */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100171 if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200172 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100173
174 seedlen = ctx->entropy_len;
175
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100176 /* 1. Concatenate entropy and additional data if any */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100177 if( additional != NULL && len != 0 )
178 {
179 memcpy( seed + seedlen, additional, len );
180 seedlen += len;
181 }
182
183 /* 2. Update state */
Gilles Peskine4d237572018-09-13 22:19:57 +0200184 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, seed, seedlen ) ) != 0 )
185 goto exit;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100186
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100187 /* 3. Reset reseed_counter */
188 ctx->reseed_counter = 1;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100189
Gilles Peskine4d237572018-09-13 22:19:57 +0200190exit:
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100191 /* 4. Done */
Gilles Peskine1da77762018-09-11 15:35:41 +0200192 mbedtls_zeroize( seed, seedlen );
Gilles Peskine4d237572018-09-13 22:19:57 +0200193 return( ret );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100194}
195
196/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100197 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100198 */
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200199int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200200 const mbedtls_md_info_t * md_info,
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100201 int (*f_entropy)(void *, unsigned char *, size_t),
202 void *p_entropy,
203 const unsigned char *custom,
204 size_t len )
205{
206 int ret;
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100207 size_t entropy_len, md_size;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100208
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200209 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100210 return( ret );
211
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200212 md_size = mbedtls_md_get_size( md_info );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100213
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100214 /*
215 * Set initial working state.
216 * Use the V memory location, which is currently all 0, to initialize the
217 * MD context with an all-zero key. Then set V to its initial value.
218 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200219 mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100220 memset( ctx->V, 0x01, md_size );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100221
222 ctx->f_entropy = f_entropy;
223 ctx->p_entropy = p_entropy;
224
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200225 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100226
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100227 /*
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100228 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
229 * each hash function, then according to SP800-90A rev1 10.1 table 2,
230 * min_entropy_len (in bits) is security_strength.
231 *
232 * (This also matches the sizes used in the NIST test vectors.)
233 */
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100234 entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
235 md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
236 32; /* better (256+) -> 256 bits */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100237
238 /*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100239 * For initialisation, use more entropy to emulate a nonce
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100240 * (Again, matches test vectors.)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100241 */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100242 ctx->entropy_len = entropy_len * 3 / 2;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100243
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200244 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100245 return( ret );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100246
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100247 ctx->entropy_len = entropy_len;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100248
249 return( 0 );
250}
251
252/*
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100253 * Set prediction resistance
254 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200255void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100256 int resistance )
257{
258 ctx->prediction_resistance = resistance;
259}
260
261/*
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100262 * Set entropy length grabbed for reseeds
263 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200264void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100265{
266 ctx->entropy_len = len;
267}
268
269/*
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100270 * Set reseed interval
271 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200272void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval )
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100273{
274 ctx->reseed_interval = interval;
275}
276
277/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100278 * HMAC_DRBG random function with optional additional data:
279 * 10.1.2.5 (arabic) + 9.3 (Roman)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100280 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200281int mbedtls_hmac_drbg_random_with_add( void *p_rng,
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100282 unsigned char *output, size_t out_len,
283 const unsigned char *additional, size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100284{
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100285 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200286 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
287 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100288 size_t left = out_len;
289 unsigned char *out = output;
290
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100291 /* II. Check request length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200292 if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST )
293 return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100294
295 /* III. Check input length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200296 if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
297 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100298
299 /* 1. (aka VII and IX) Check reseed counter and PR */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100300 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200301 ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100302 ctx->reseed_counter > ctx->reseed_interval ) )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100303 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200304 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100305 return( ret );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100306
307 add_len = 0; /* VII.4 */
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100308 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100309
310 /* 2. Use additional data if any */
311 if( additional != NULL && add_len != 0 )
Gilles Peskine4d237572018-09-13 22:19:57 +0200312 {
313 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
314 additional, add_len ) ) != 0 )
315 goto exit;
316 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100317
318 /* 3, 4, 5. Generate bytes */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100319 while( left != 0 )
320 {
321 size_t use_len = left > md_len ? md_len : left;
322
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200323 mbedtls_md_hmac_reset( &ctx->md_ctx );
324 mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
325 mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100326
327 memcpy( out, ctx->V, use_len );
328 out += use_len;
329 left -= use_len;
330 }
331
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100332 /* 6. Update */
Gilles Peskine4d237572018-09-13 22:19:57 +0200333 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
334 additional, add_len ) ) != 0 )
335 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100336
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100337 /* 7. Update reseed counter */
338 ctx->reseed_counter++;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100339
Gilles Peskine4d237572018-09-13 22:19:57 +0200340exit:
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100341 /* 8. Done */
Gilles Peskine4d237572018-09-13 22:19:57 +0200342 return( ret );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100343}
344
345/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100346 * HMAC_DRBG random function
347 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200348int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100349{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100350 int ret;
351 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
352
353#if defined(MBEDTLS_THREADING_C)
354 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
355 return( ret );
356#endif
357
358 ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
359
360#if defined(MBEDTLS_THREADING_C)
361 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
362 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
363#endif
364
365 return( ret );
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100366}
367
368/*
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100369 * Free an HMAC_DRBG context
370 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200371void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100372{
373 if( ctx == NULL )
374 return;
375
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100376#if defined(MBEDTLS_THREADING_C)
377 mbedtls_mutex_free( &ctx->mutex );
378#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200379 mbedtls_md_free( &ctx->md_ctx );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200380 mbedtls_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100381}
382
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200383#if defined(MBEDTLS_FS_IO)
384int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100385{
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100386 int ret;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100387 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200388 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100389
390 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200391 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100392
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200393 if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100394 goto exit;
395
396 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
397 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200398 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
Paul Bakker4c284c92014-03-26 15:33:05 +0100399 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100400 }
401
402 ret = 0;
403
404exit:
405 fclose( f );
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100406 mbedtls_zeroize( buf, sizeof( buf ) );
407
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100408 return( ret );
409}
410
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200411int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100412{
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100413 int ret = 0;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100414 FILE *f;
415 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200416 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100417
418 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200419 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100420
421 fseek( f, 0, SEEK_END );
422 n = (size_t) ftell( f );
423 fseek( f, 0, SEEK_SET );
424
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200425 if( n > MBEDTLS_HMAC_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100426 {
427 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200428 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100429 }
430
431 if( fread( buf, 1, n, f ) != n )
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100432 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
433 else
Gilles Peskine4d237572018-09-13 22:19:57 +0200434 ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100435 fclose( f );
436
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100437 mbedtls_zeroize( buf, sizeof( buf ) );
438
439 if( ret != 0 )
440 return( ret );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100441
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200442 return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100443}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200444#endif /* MBEDTLS_FS_IO */
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100445
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100446
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200447#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100448
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449#if !defined(MBEDTLS_SHA1_C)
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100450/* Dummy checkup routine */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200451int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100452{
Manuel Pégourié-Gonnardd1004f02015-08-07 10:46:54 +0200453 (void) verbose;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100454 return( 0 );
455}
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100456#else
457
458#define OUTPUT_LEN 80
459
460/* From a NIST PR=true test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000461static const unsigned char entropy_pr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100462 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
463 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
464 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
465 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
466 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
467static const unsigned char result_pr[OUTPUT_LEN] = {
468 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
469 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
470 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
471 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
472 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
473 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
474 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
475
476/* From a NIST PR=false test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000477static const unsigned char entropy_nopr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100478 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
479 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
480 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
481 0xe9, 0x9d, 0xfe, 0xdf };
482static const unsigned char result_nopr[OUTPUT_LEN] = {
483 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
484 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
485 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
486 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
487 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
488 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
489 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
490
491/* "Entropy" from buffer */
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100492static size_t test_offset;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100493static int hmac_drbg_self_test_entropy( void *data,
494 unsigned char *buf, size_t len )
495{
496 const unsigned char *p = data;
497 memcpy( buf, p + test_offset, len );
498 test_offset += len;
499 return( 0 );
500}
501
Paul Bakker7dc4c442014-02-01 22:50:26 +0100502#define CHK( c ) if( (c) != 0 ) \
503 { \
504 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200505 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100506 return( 1 ); \
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100507 }
508
509/*
510 * Checkup routine for HMAC_DRBG with SHA-1
511 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200512int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100513{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200514 mbedtls_hmac_drbg_context ctx;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100515 unsigned char buf[OUTPUT_LEN];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200516 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100517
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200518 mbedtls_hmac_drbg_init( &ctx );
519
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100520 /*
521 * PR = True
522 */
523 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200524 mbedtls_printf( " HMAC_DRBG (PR = True) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100525
526 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200527 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000528 hmac_drbg_self_test_entropy, (void *) entropy_pr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100529 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200530 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
531 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
532 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100533 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200534 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100535
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100536 mbedtls_hmac_drbg_free( &ctx );
537
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100538 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200539 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100540
541 /*
542 * PR = False
543 */
544 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200545 mbedtls_printf( " HMAC_DRBG (PR = False) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100546
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100547 mbedtls_hmac_drbg_init( &ctx );
548
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100549 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200550 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000551 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100552 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200553 CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
554 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
555 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100556 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200557 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100558
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100559 mbedtls_hmac_drbg_free( &ctx );
560
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100561 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200562 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100563
564 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200565 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100566
567 return( 0 );
568}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200569#endif /* MBEDTLS_SHA1_C */
570#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100571
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200572#endif /* MBEDTLS_HMAC_DRBG_C */