blob: 24c609e9ce964ce87845c2a98eb2f0c423cd7ae9 [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 }
96}
97
98/*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +010099 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100100 */
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200101int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200102 const mbedtls_md_info_t * md_info,
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100103 const unsigned char *data, size_t data_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100104{
105 int ret;
106
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200107 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100108 return( ret );
109
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100110 /*
111 * Set initial working state.
112 * Use the V memory location, which is currently all 0, to initialize the
113 * MD context with an all-zero key. Then set V to its initial value.
114 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200115 mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, mbedtls_md_get_size( md_info ) );
116 memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100117
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200118 mbedtls_hmac_drbg_update( ctx, data, data_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100119
120 return( 0 );
121}
122
123/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100124 * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100125 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200126int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100127 const unsigned char *additional, size_t len )
128{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200129 unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100130 size_t seedlen;
131
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100132 /* III. Check input length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200133 if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
134 ctx->entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100135 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200136 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100137 }
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100138
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200139 memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100140
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100141 /* IV. Gather entropy_len bytes of entropy for the seed */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100142 if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200143 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100144
145 seedlen = ctx->entropy_len;
146
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100147 /* 1. Concatenate entropy and additional data if any */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100148 if( additional != NULL && len != 0 )
149 {
150 memcpy( seed + seedlen, additional, len );
151 seedlen += len;
152 }
153
154 /* 2. Update state */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200155 mbedtls_hmac_drbg_update( ctx, seed, seedlen );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100156
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100157 /* 3. Reset reseed_counter */
158 ctx->reseed_counter = 1;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100159
160 /* 4. Done */
161 return( 0 );
162}
163
164/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100165 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100166 */
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200167int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200168 const mbedtls_md_info_t * md_info,
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100169 int (*f_entropy)(void *, unsigned char *, size_t),
170 void *p_entropy,
171 const unsigned char *custom,
172 size_t len )
173{
174 int ret;
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100175 size_t entropy_len, md_size;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100176
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200177 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100178 return( ret );
179
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200180 md_size = mbedtls_md_get_size( md_info );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100181
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100182 /*
183 * Set initial working state.
184 * Use the V memory location, which is currently all 0, to initialize the
185 * MD context with an all-zero key. Then set V to its initial value.
186 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200187 mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size );
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100188 memset( ctx->V, 0x01, md_size );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100189
190 ctx->f_entropy = f_entropy;
191 ctx->p_entropy = p_entropy;
192
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200193 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100194
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100195 /*
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100196 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
197 * each hash function, then according to SP800-90A rev1 10.1 table 2,
198 * min_entropy_len (in bits) is security_strength.
199 *
200 * (This also matches the sizes used in the NIST test vectors.)
201 */
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100202 entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
203 md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
204 32; /* better (256+) -> 256 bits */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100205
206 /*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100207 * For initialisation, use more entropy to emulate a nonce
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100208 * (Again, matches test vectors.)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100209 */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100210 ctx->entropy_len = entropy_len * 3 / 2;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100211
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200212 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100213 return( ret );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100214
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100215 ctx->entropy_len = entropy_len;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100216
217 return( 0 );
218}
219
220/*
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100221 * Set prediction resistance
222 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200223void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100224 int resistance )
225{
226 ctx->prediction_resistance = resistance;
227}
228
229/*
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100230 * Set entropy length grabbed for reseeds
231 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200232void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100233{
234 ctx->entropy_len = len;
235}
236
237/*
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100238 * Set reseed interval
239 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200240void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval )
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100241{
242 ctx->reseed_interval = interval;
243}
244
245/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100246 * HMAC_DRBG random function with optional additional data:
247 * 10.1.2.5 (arabic) + 9.3 (Roman)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100248 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200249int mbedtls_hmac_drbg_random_with_add( void *p_rng,
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100250 unsigned char *output, size_t out_len,
251 const unsigned char *additional, size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100252{
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100253 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200254 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
255 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100256 size_t left = out_len;
257 unsigned char *out = output;
258
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100259 /* II. Check request length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200260 if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST )
261 return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100262
263 /* III. Check input length */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200264 if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
265 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100266
267 /* 1. (aka VII and IX) Check reseed counter and PR */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100268 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200269 ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100270 ctx->reseed_counter > ctx->reseed_interval ) )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100271 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200272 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100273 return( ret );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100274
275 add_len = 0; /* VII.4 */
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100276 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100277
278 /* 2. Use additional data if any */
279 if( additional != NULL && add_len != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200280 mbedtls_hmac_drbg_update( ctx, additional, add_len );
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100281
282 /* 3, 4, 5. Generate bytes */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100283 while( left != 0 )
284 {
285 size_t use_len = left > md_len ? md_len : left;
286
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200287 mbedtls_md_hmac_reset( &ctx->md_ctx );
288 mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
289 mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100290
291 memcpy( out, ctx->V, use_len );
292 out += use_len;
293 left -= use_len;
294 }
295
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100296 /* 6. Update */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200297 mbedtls_hmac_drbg_update( ctx, additional, add_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100298
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100299 /* 7. Update reseed counter */
300 ctx->reseed_counter++;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100301
302 /* 8. Done */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100303 return( 0 );
304}
305
306/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100307 * HMAC_DRBG random function
308 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200309int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100310{
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100311 int ret;
312 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
313
314#if defined(MBEDTLS_THREADING_C)
315 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
316 return( ret );
317#endif
318
319 ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
320
321#if defined(MBEDTLS_THREADING_C)
322 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
323 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
324#endif
325
326 return( ret );
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100327}
328
329/*
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100330 * Free an HMAC_DRBG context
331 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200332void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100333{
334 if( ctx == NULL )
335 return;
336
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100337#if defined(MBEDTLS_THREADING_C)
338 mbedtls_mutex_free( &ctx->mutex );
339#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200340 mbedtls_md_free( &ctx->md_ctx );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200341 mbedtls_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100342}
343
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200344#if defined(MBEDTLS_FS_IO)
345int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100346{
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100347 int ret;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100348 FILE *f;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200349 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100350
351 if( ( f = fopen( path, "wb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200352 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100353
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200354 if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100355 goto exit;
356
357 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
358 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200359 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
Paul Bakker4c284c92014-03-26 15:33:05 +0100360 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100361 }
362
363 ret = 0;
364
365exit:
366 fclose( f );
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100367 mbedtls_zeroize( buf, sizeof( buf ) );
368
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100369 return( ret );
370}
371
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200372int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100373{
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100374 int ret = 0;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100375 FILE *f;
376 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200377 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100378
379 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200380 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100381
382 fseek( f, 0, SEEK_END );
383 n = (size_t) ftell( f );
384 fseek( f, 0, SEEK_SET );
385
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200386 if( n > MBEDTLS_HMAC_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100387 {
388 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200389 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100390 }
391
392 if( fread( buf, 1, n, f ) != n )
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100393 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
394 else
395 mbedtls_hmac_drbg_update( ctx, buf, n );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100396
397 fclose( f );
398
Andres Amaya Garcia3fee7592017-06-26 10:22:24 +0100399 mbedtls_zeroize( buf, sizeof( buf ) );
400
401 if( ret != 0 )
402 return( ret );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100403
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200404 return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100405}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200406#endif /* MBEDTLS_FS_IO */
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100407
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100408
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200409#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100410
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200411#if !defined(MBEDTLS_SHA1_C)
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100412/* Dummy checkup routine */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200413int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100414{
Manuel Pégourié-Gonnardd1004f02015-08-07 10:46:54 +0200415 (void) verbose;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100416 return( 0 );
417}
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100418#else
419
420#define OUTPUT_LEN 80
421
422/* From a NIST PR=true test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000423static const unsigned char entropy_pr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100424 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
425 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
426 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
427 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
428 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
429static const unsigned char result_pr[OUTPUT_LEN] = {
430 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
431 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
432 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
433 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
434 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
435 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
436 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
437
438/* From a NIST PR=false test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000439static const unsigned char entropy_nopr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100440 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
441 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
442 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
443 0xe9, 0x9d, 0xfe, 0xdf };
444static const unsigned char result_nopr[OUTPUT_LEN] = {
445 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
446 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
447 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
448 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
449 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
450 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
451 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
452
453/* "Entropy" from buffer */
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100454static size_t test_offset;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100455static int hmac_drbg_self_test_entropy( void *data,
456 unsigned char *buf, size_t len )
457{
458 const unsigned char *p = data;
459 memcpy( buf, p + test_offset, len );
460 test_offset += len;
461 return( 0 );
462}
463
Paul Bakker7dc4c442014-02-01 22:50:26 +0100464#define CHK( c ) if( (c) != 0 ) \
465 { \
466 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200467 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100468 return( 1 ); \
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100469 }
470
471/*
472 * Checkup routine for HMAC_DRBG with SHA-1
473 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200474int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100475{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200476 mbedtls_hmac_drbg_context ctx;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100477 unsigned char buf[OUTPUT_LEN];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200478 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100479
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200480 mbedtls_hmac_drbg_init( &ctx );
481
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100482 /*
483 * PR = True
484 */
485 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200486 mbedtls_printf( " HMAC_DRBG (PR = True) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100487
488 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200489 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000490 hmac_drbg_self_test_entropy, (void *) entropy_pr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100491 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200492 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
493 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
494 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100495 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200496 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100497
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100498 mbedtls_hmac_drbg_free( &ctx );
499
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100500 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200501 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100502
503 /*
504 * PR = False
505 */
506 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200507 mbedtls_printf( " HMAC_DRBG (PR = False) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100508
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100509 mbedtls_hmac_drbg_init( &ctx );
510
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100511 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200512 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000513 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100514 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200515 CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
516 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
517 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100518 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200519 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100520
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100521 mbedtls_hmac_drbg_free( &ctx );
522
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100523 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200524 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100525
526 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200527 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100528
529 return( 0 );
530}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200531#endif /* MBEDTLS_SHA1_C */
532#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100533
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200534#endif /* MBEDTLS_HMAC_DRBG_C */