blob: 9801bc50d8f731ec1c008663f0dc7ac24bb7da7b [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 */
Gilles Peskineaadc8182018-09-11 16:54:57 +0200142 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V,
143 mbedtls_md_get_size( md_info ) ) ) != 0 )
144 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200145 memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100146
Gilles Peskine4d237572018-09-13 22:19:57 +0200147 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, data, data_len ) ) != 0 )
148 return( ret );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100149
150 return( 0 );
151}
152
153/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100154 * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100155 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200156int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100157 const unsigned char *additional, size_t len )
158{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200159 unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100160 size_t seedlen;
Gilles Peskine4d237572018-09-13 22:19:57 +0200161 int ret;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100162
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100163 /* III. Check input length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200164 if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
165 ctx->entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100166 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200167 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100168 }
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100169
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200170 memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100171
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100172 /* IV. Gather entropy_len bytes of entropy for the seed */
Gilles Peskineaadc8182018-09-11 16:54:57 +0200173 if( ( ret = ctx->f_entropy( ctx->p_entropy,
174 seed, ctx->entropy_len ) ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200175 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100176
177 seedlen = ctx->entropy_len;
178
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100179 /* 1. Concatenate entropy and additional data if any */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100180 if( additional != NULL && len != 0 )
181 {
182 memcpy( seed + seedlen, additional, len );
183 seedlen += len;
184 }
185
186 /* 2. Update state */
Gilles Peskine4d237572018-09-13 22:19:57 +0200187 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, seed, seedlen ) ) != 0 )
188 goto exit;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100189
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100190 /* 3. Reset reseed_counter */
191 ctx->reseed_counter = 1;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100192
Gilles Peskine4d237572018-09-13 22:19:57 +0200193exit:
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100194 /* 4. Done */
Gilles Peskine1da77762018-09-11 15:35:41 +0200195 mbedtls_zeroize( seed, seedlen );
Gilles Peskine4d237572018-09-13 22:19:57 +0200196 return( ret );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100197}
198
199/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100200 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100201 */
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200202int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200203 const mbedtls_md_info_t * md_info,
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100204 int (*f_entropy)(void *, unsigned char *, size_t),
205 void *p_entropy,
206 const unsigned char *custom,
207 size_t len )
208{
209 int ret;
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100210 size_t entropy_len, md_size;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100211
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200212 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100213 return( ret );
214
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200215 md_size = mbedtls_md_get_size( md_info );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100216
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100217 /*
218 * Set initial working state.
219 * Use the V memory location, which is currently all 0, to initialize the
220 * MD context with an all-zero key. Then set V to its initial value.
221 */
Gilles Peskineaadc8182018-09-11 16:54:57 +0200222 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ) ) != 0 )
223 return( ret );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100224 memset( ctx->V, 0x01, md_size );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100225
226 ctx->f_entropy = f_entropy;
227 ctx->p_entropy = p_entropy;
228
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200229 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100230
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100231 /*
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100232 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
233 * each hash function, then according to SP800-90A rev1 10.1 table 2,
234 * min_entropy_len (in bits) is security_strength.
235 *
236 * (This also matches the sizes used in the NIST test vectors.)
237 */
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100238 entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
239 md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
240 32; /* better (256+) -> 256 bits */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100241
242 /*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100243 * For initialisation, use more entropy to emulate a nonce
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100244 * (Again, matches test vectors.)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100245 */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100246 ctx->entropy_len = entropy_len * 3 / 2;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100247
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200248 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100249 return( ret );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100250
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100251 ctx->entropy_len = entropy_len;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100252
253 return( 0 );
254}
255
256/*
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100257 * Set prediction resistance
258 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200259void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100260 int resistance )
261{
262 ctx->prediction_resistance = resistance;
263}
264
265/*
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100266 * Set entropy length grabbed for reseeds
267 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200268void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100269{
270 ctx->entropy_len = len;
271}
272
273/*
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100274 * Set reseed interval
275 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200276void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval )
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100277{
278 ctx->reseed_interval = interval;
279}
280
281/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100282 * HMAC_DRBG random function with optional additional data:
283 * 10.1.2.5 (arabic) + 9.3 (Roman)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100284 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200285int mbedtls_hmac_drbg_random_with_add( void *p_rng,
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100286 unsigned char *output, size_t out_len,
287 const unsigned char *additional, size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100288{
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100289 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200290 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
291 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100292 size_t left = out_len;
293 unsigned char *out = output;
294
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100295 /* II. Check request length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200296 if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST )
297 return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100298
299 /* III. Check input length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200300 if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
301 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100302
303 /* 1. (aka VII and IX) Check reseed counter and PR */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100304 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200305 ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100306 ctx->reseed_counter > ctx->reseed_interval ) )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100307 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200308 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100309 return( ret );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100310
311 add_len = 0; /* VII.4 */
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100312 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100313
314 /* 2. Use additional data if any */
315 if( additional != NULL && add_len != 0 )
Gilles Peskine4d237572018-09-13 22:19:57 +0200316 {
317 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
318 additional, add_len ) ) != 0 )
319 goto exit;
320 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100321
322 /* 3, 4, 5. Generate bytes */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100323 while( left != 0 )
324 {
325 size_t use_len = left > md_len ? md_len : left;
326
Gilles Peskineaadc8182018-09-11 16:54:57 +0200327 if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
328 goto exit;
329 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
330 ctx->V, md_len ) ) != 0 )
331 goto exit;
332 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
333 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100334
335 memcpy( out, ctx->V, use_len );
336 out += use_len;
337 left -= use_len;
338 }
339
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100340 /* 6. Update */
Gilles Peskine4d237572018-09-13 22:19:57 +0200341 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
342 additional, add_len ) ) != 0 )
343 goto exit;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100344
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100345 /* 7. Update reseed counter */
346 ctx->reseed_counter++;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100347
Gilles Peskine4d237572018-09-13 22:19:57 +0200348exit:
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100349 /* 8. Done */
Gilles Peskine4d237572018-09-13 22:19:57 +0200350 return( ret );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100351}
352
353/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100354 * HMAC_DRBG random function
355 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200356int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100357{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100358 int ret;
359 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
360
361#if defined(MBEDTLS_THREADING_C)
362 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
363 return( ret );
364#endif
365
366 ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
367
368#if defined(MBEDTLS_THREADING_C)
369 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
370 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
371#endif
372
373 return( ret );
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100374}
375
376/*
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100377 * Free an HMAC_DRBG context
378 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200379void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100380{
381 if( ctx == NULL )
382 return;
383
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100384#if defined(MBEDTLS_THREADING_C)
385 mbedtls_mutex_free( &ctx->mutex );
386#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200387 mbedtls_md_free( &ctx->md_ctx );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200388 mbedtls_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100389}
390
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200391#if defined(MBEDTLS_FS_IO)
392int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100393{
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100394 int ret;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100395 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200396 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100397
398 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200399 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100400
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200401 if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100402 goto exit;
403
404 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
405 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200406 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
Paul Bakker4c284c92014-03-26 15:33:05 +0100407 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100408 }
409
410 ret = 0;
411
412exit:
413 fclose( f );
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100414 mbedtls_zeroize( buf, sizeof( buf ) );
415
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100416 return( ret );
417}
418
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200419int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100420{
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100421 int ret = 0;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100422 FILE *f;
423 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200424 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100425
426 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200427 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100428
429 fseek( f, 0, SEEK_END );
430 n = (size_t) ftell( f );
431 fseek( f, 0, SEEK_SET );
432
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200433 if( n > MBEDTLS_HMAC_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100434 {
435 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200436 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100437 }
438
439 if( fread( buf, 1, n, f ) != n )
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100440 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
441 else
Gilles Peskine4d237572018-09-13 22:19:57 +0200442 ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n );
Gilles Peskineaadc8182018-09-11 16:54:57 +0200443
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100444 fclose( f );
445
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100446 mbedtls_zeroize( buf, sizeof( buf ) );
447
448 if( ret != 0 )
449 return( ret );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100450
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200451 return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100452}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200453#endif /* MBEDTLS_FS_IO */
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100454
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100455
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200456#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100457
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200458#if !defined(MBEDTLS_SHA1_C)
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100459/* Dummy checkup routine */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200460int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100461{
Manuel Pégourié-Gonnardd1004f02015-08-07 10:46:54 +0200462 (void) verbose;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100463 return( 0 );
464}
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100465#else
466
467#define OUTPUT_LEN 80
468
469/* From a NIST PR=true test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000470static const unsigned char entropy_pr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100471 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
472 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
473 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
474 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
475 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
476static const unsigned char result_pr[OUTPUT_LEN] = {
477 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
478 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
479 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
480 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
481 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
482 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
483 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
484
485/* From a NIST PR=false test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000486static const unsigned char entropy_nopr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100487 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
488 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
489 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
490 0xe9, 0x9d, 0xfe, 0xdf };
491static const unsigned char result_nopr[OUTPUT_LEN] = {
492 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
493 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
494 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
495 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
496 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
497 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
498 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
499
500/* "Entropy" from buffer */
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100501static size_t test_offset;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100502static int hmac_drbg_self_test_entropy( void *data,
503 unsigned char *buf, size_t len )
504{
505 const unsigned char *p = data;
506 memcpy( buf, p + test_offset, len );
507 test_offset += len;
508 return( 0 );
509}
510
Paul Bakker7dc4c442014-02-01 22:50:26 +0100511#define CHK( c ) if( (c) != 0 ) \
512 { \
513 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200514 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100515 return( 1 ); \
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100516 }
517
518/*
519 * Checkup routine for HMAC_DRBG with SHA-1
520 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200521int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100522{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200523 mbedtls_hmac_drbg_context ctx;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100524 unsigned char buf[OUTPUT_LEN];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200525 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100526
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200527 mbedtls_hmac_drbg_init( &ctx );
528
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100529 /*
530 * PR = True
531 */
532 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200533 mbedtls_printf( " HMAC_DRBG (PR = True) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100534
535 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200536 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000537 hmac_drbg_self_test_entropy, (void *) entropy_pr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100538 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200539 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
540 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
541 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100542 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200543 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100544
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100545 mbedtls_hmac_drbg_free( &ctx );
546
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100547 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200548 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100549
550 /*
551 * PR = False
552 */
553 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200554 mbedtls_printf( " HMAC_DRBG (PR = False) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100555
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100556 mbedtls_hmac_drbg_init( &ctx );
557
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100558 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200559 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000560 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100561 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200562 CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
563 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
564 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100565 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200566 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100567
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100568 mbedtls_hmac_drbg_free( &ctx );
569
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100570 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200571 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100572
573 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200574 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100575
576 return( 0 );
577}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200578#endif /* MBEDTLS_SHA1_C */
579#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100580
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200581#endif /* MBEDTLS_HMAC_DRBG_C */