blob: 40e2b0ad6adc751c14bfb4bccd8fb3f3db96268e [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 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020073void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010074 const unsigned char *additional, size_t add_len )
75{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020076 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010077 unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
78 unsigned char sep[1];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020079 unsigned char K[MBEDTLS_MD_MAX_SIZE];
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010080
81 for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
82 {
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010083 /* Step 1 or 4 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020084 mbedtls_md_hmac_reset( &ctx->md_ctx );
85 mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
86 mbedtls_md_hmac_update( &ctx->md_ctx, sep, 1 );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010087 if( rounds == 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020088 mbedtls_md_hmac_update( &ctx->md_ctx, additional, add_len );
89 mbedtls_md_hmac_finish( &ctx->md_ctx, K );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010090
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010091 /* Step 2 or 5 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020092 mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len );
93 mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
94 mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010095 }
Gilles Peskine51de2d22018-09-11 15:35:41 +020096
97 mbedtls_zeroize( K, sizeof( K ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010098}
99
100/*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100101 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100102 */
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200103int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200104 const mbedtls_md_info_t * md_info,
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100105 const unsigned char *data, size_t data_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100106{
107 int ret;
108
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200109 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100110 return( ret );
111
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100112 /*
113 * Set initial working state.
114 * Use the V memory location, which is currently all 0, to initialize the
115 * MD context with an all-zero key. Then set V to its initial value.
116 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200117 mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, mbedtls_md_get_size( md_info ) );
118 memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100119
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200120 mbedtls_hmac_drbg_update( ctx, data, data_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100121
122 return( 0 );
123}
124
125/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100126 * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100127 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200128int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100129 const unsigned char *additional, size_t len )
130{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200131 unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100132 size_t seedlen;
133
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100134 /* III. Check input length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200135 if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
136 ctx->entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100137 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200138 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100139 }
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100140
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200141 memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100142
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100143 /* IV. Gather entropy_len bytes of entropy for the seed */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100144 if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200145 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100146
147 seedlen = ctx->entropy_len;
148
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100149 /* 1. Concatenate entropy and additional data if any */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100150 if( additional != NULL && len != 0 )
151 {
152 memcpy( seed + seedlen, additional, len );
153 seedlen += len;
154 }
155
156 /* 2. Update state */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200157 mbedtls_hmac_drbg_update( ctx, seed, seedlen );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100158
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100159 /* 3. Reset reseed_counter */
160 ctx->reseed_counter = 1;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100161
162 /* 4. Done */
Gilles Peskine51de2d22018-09-11 15:35:41 +0200163 mbedtls_zeroize( seed, seedlen );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100164 return( 0 );
165}
166
167/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100168 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100169 */
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200170int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200171 const mbedtls_md_info_t * md_info,
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100172 int (*f_entropy)(void *, unsigned char *, size_t),
173 void *p_entropy,
174 const unsigned char *custom,
175 size_t len )
176{
177 int ret;
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100178 size_t entropy_len, md_size;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100179
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200180 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100181 return( ret );
182
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200183 md_size = mbedtls_md_get_size( md_info );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100184
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100185 /*
186 * Set initial working state.
187 * Use the V memory location, which is currently all 0, to initialize the
188 * MD context with an all-zero key. Then set V to its initial value.
189 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200190 mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100191 memset( ctx->V, 0x01, md_size );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100192
193 ctx->f_entropy = f_entropy;
194 ctx->p_entropy = p_entropy;
195
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200196 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100197
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100198 /*
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100199 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
200 * each hash function, then according to SP800-90A rev1 10.1 table 2,
201 * min_entropy_len (in bits) is security_strength.
202 *
203 * (This also matches the sizes used in the NIST test vectors.)
204 */
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100205 entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
206 md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
207 32; /* better (256+) -> 256 bits */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100208
209 /*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100210 * For initialisation, use more entropy to emulate a nonce
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100211 * (Again, matches test vectors.)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100212 */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100213 ctx->entropy_len = entropy_len * 3 / 2;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100214
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200215 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100216 return( ret );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100217
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100218 ctx->entropy_len = entropy_len;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100219
220 return( 0 );
221}
222
223/*
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100224 * Set prediction resistance
225 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200226void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100227 int resistance )
228{
229 ctx->prediction_resistance = resistance;
230}
231
232/*
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100233 * Set entropy length grabbed for reseeds
234 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200235void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100236{
237 ctx->entropy_len = len;
238}
239
240/*
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100241 * Set reseed interval
242 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200243void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval )
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100244{
245 ctx->reseed_interval = interval;
246}
247
248/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100249 * HMAC_DRBG random function with optional additional data:
250 * 10.1.2.5 (arabic) + 9.3 (Roman)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100251 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200252int mbedtls_hmac_drbg_random_with_add( void *p_rng,
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100253 unsigned char *output, size_t out_len,
254 const unsigned char *additional, size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100255{
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100256 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200257 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
258 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100259 size_t left = out_len;
260 unsigned char *out = output;
261
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100262 /* II. Check request length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200263 if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST )
264 return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100265
266 /* III. Check input length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200267 if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
268 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100269
270 /* 1. (aka VII and IX) Check reseed counter and PR */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100271 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200272 ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100273 ctx->reseed_counter > ctx->reseed_interval ) )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100274 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200275 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100276 return( ret );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100277
278 add_len = 0; /* VII.4 */
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100279 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100280
281 /* 2. Use additional data if any */
282 if( additional != NULL && add_len != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200283 mbedtls_hmac_drbg_update( ctx, additional, add_len );
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100284
285 /* 3, 4, 5. Generate bytes */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100286 while( left != 0 )
287 {
288 size_t use_len = left > md_len ? md_len : left;
289
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200290 mbedtls_md_hmac_reset( &ctx->md_ctx );
291 mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
292 mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100293
294 memcpy( out, ctx->V, use_len );
295 out += use_len;
296 left -= use_len;
297 }
298
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100299 /* 6. Update */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200300 mbedtls_hmac_drbg_update( ctx, additional, add_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100301
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100302 /* 7. Update reseed counter */
303 ctx->reseed_counter++;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100304
305 /* 8. Done */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100306 return( 0 );
307}
308
309/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100310 * HMAC_DRBG random function
311 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200312int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100313{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100314 int ret;
315 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
316
317#if defined(MBEDTLS_THREADING_C)
318 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
319 return( ret );
320#endif
321
322 ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
323
324#if defined(MBEDTLS_THREADING_C)
325 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
326 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
327#endif
328
329 return( ret );
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100330}
331
332/*
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100333 * Free an HMAC_DRBG context
334 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200335void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100336{
337 if( ctx == NULL )
338 return;
339
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100340#if defined(MBEDTLS_THREADING_C)
341 mbedtls_mutex_free( &ctx->mutex );
342#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200343 mbedtls_md_free( &ctx->md_ctx );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200344 mbedtls_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100345}
346
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200347#if defined(MBEDTLS_FS_IO)
348int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100349{
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100350 int ret;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100351 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200352 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100353
354 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200355 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100356
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200357 if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100358 goto exit;
359
360 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
361 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200362 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
Paul Bakker4c284c92014-03-26 15:33:05 +0100363 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100364 }
365
366 ret = 0;
367
368exit:
369 fclose( f );
Andres Amaya Garciaf1131612017-06-26 10:22:24 +0100370 mbedtls_zeroize( buf, sizeof( buf ) );
371
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100372 return( ret );
373}
374
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200375int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100376{
Andres Amaya Garciaf1131612017-06-26 10:22:24 +0100377 int ret = 0;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100378 FILE *f;
379 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200380 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100381
382 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200383 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100384
385 fseek( f, 0, SEEK_END );
386 n = (size_t) ftell( f );
387 fseek( f, 0, SEEK_SET );
388
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200389 if( n > MBEDTLS_HMAC_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100390 {
391 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200392 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100393 }
394
395 if( fread( buf, 1, n, f ) != n )
Andres Amaya Garciaf1131612017-06-26 10:22:24 +0100396 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
397 else
398 mbedtls_hmac_drbg_update( ctx, buf, n );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100399
400 fclose( f );
401
Andres Amaya Garciaf1131612017-06-26 10:22:24 +0100402 mbedtls_zeroize( buf, sizeof( buf ) );
403
404 if( ret != 0 )
405 return( ret );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100406
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200407 return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100408}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200409#endif /* MBEDTLS_FS_IO */
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100410
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100411
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200412#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100413
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200414#if !defined(MBEDTLS_SHA1_C)
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100415/* Dummy checkup routine */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200416int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100417{
Manuel Pégourié-Gonnardd1004f02015-08-07 10:46:54 +0200418 (void) verbose;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100419 return( 0 );
420}
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100421#else
422
423#define OUTPUT_LEN 80
424
425/* From a NIST PR=true test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000426static const unsigned char entropy_pr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100427 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
428 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
429 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
430 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
431 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
432static const unsigned char result_pr[OUTPUT_LEN] = {
433 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
434 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
435 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
436 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
437 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
438 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
439 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
440
441/* From a NIST PR=false test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000442static const unsigned char entropy_nopr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100443 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
444 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
445 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
446 0xe9, 0x9d, 0xfe, 0xdf };
447static const unsigned char result_nopr[OUTPUT_LEN] = {
448 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
449 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
450 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
451 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
452 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
453 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
454 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
455
456/* "Entropy" from buffer */
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100457static size_t test_offset;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100458static int hmac_drbg_self_test_entropy( void *data,
459 unsigned char *buf, size_t len )
460{
461 const unsigned char *p = data;
462 memcpy( buf, p + test_offset, len );
463 test_offset += len;
464 return( 0 );
465}
466
Paul Bakker7dc4c442014-02-01 22:50:26 +0100467#define CHK( c ) if( (c) != 0 ) \
468 { \
469 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200470 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100471 return( 1 ); \
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100472 }
473
474/*
475 * Checkup routine for HMAC_DRBG with SHA-1
476 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200477int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100478{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200479 mbedtls_hmac_drbg_context ctx;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100480 unsigned char buf[OUTPUT_LEN];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100482
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200483 mbedtls_hmac_drbg_init( &ctx );
484
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100485 /*
486 * PR = True
487 */
488 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200489 mbedtls_printf( " HMAC_DRBG (PR = True) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100490
491 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200492 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000493 hmac_drbg_self_test_entropy, (void *) entropy_pr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100494 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200495 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
496 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
497 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100498 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200499 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100500
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100501 mbedtls_hmac_drbg_free( &ctx );
502
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100503 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200504 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100505
506 /*
507 * PR = False
508 */
509 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200510 mbedtls_printf( " HMAC_DRBG (PR = False) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100511
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100512 mbedtls_hmac_drbg_init( &ctx );
513
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100514 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200515 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000516 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100517 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200518 CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
519 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
520 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100521 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200522 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100523
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100524 mbedtls_hmac_drbg_free( &ctx );
525
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100526 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200527 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100528
529 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200530 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100531
532 return( 0 );
533}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200534#endif /* MBEDTLS_SHA1_C */
535#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100536
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200537#endif /* MBEDTLS_HMAC_DRBG_C */