blob: bf5f9b5bd3d43f24ef0820c654dd15315b691ef9 [file] [log] [blame] [raw]
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;
Paul Bakker84bbeb52014-07-01 14:53:22 +0200176
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;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100192
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200193 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100194
195 /*
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 );
367 return( ret );
368}
369
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200370int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100371{
372 FILE *f;
373 size_t n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200374 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100375
376 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200377 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100378
379 fseek( f, 0, SEEK_END );
380 n = (size_t) ftell( f );
381 fseek( f, 0, SEEK_SET );
382
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200383 if( n > MBEDTLS_HMAC_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100384 {
385 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200386 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100387 }
388
389 if( fread( buf, 1, n, f ) != n )
390 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100391 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200392 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100393 }
394
395 fclose( f );
396
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200397 mbedtls_hmac_drbg_update( ctx, buf, n );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100398
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200399 return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100400}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200401#endif /* MBEDTLS_FS_IO */
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100402
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100403
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200404#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100405
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200406#if !defined(MBEDTLS_SHA1_C)
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100407/* Dummy checkup routine */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200408int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100409{
Manuel Pégourié-Gonnardd1004f02015-08-07 10:46:54 +0200410 (void) verbose;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100411 return( 0 );
412}
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100413#else
414
415#define OUTPUT_LEN 80
416
417/* From a NIST PR=true test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000418static const unsigned char entropy_pr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100419 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
420 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
421 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
422 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
423 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
424static const unsigned char result_pr[OUTPUT_LEN] = {
425 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
426 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
427 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
428 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
429 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
430 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
431 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
432
433/* From a NIST PR=false test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000434static const unsigned char entropy_nopr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100435 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
436 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
437 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
438 0xe9, 0x9d, 0xfe, 0xdf };
439static const unsigned char result_nopr[OUTPUT_LEN] = {
440 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
441 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
442 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
443 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
444 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
445 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
446 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
447
448/* "Entropy" from buffer */
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100449static size_t test_offset;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100450static int hmac_drbg_self_test_entropy( void *data,
451 unsigned char *buf, size_t len )
452{
453 const unsigned char *p = data;
454 memcpy( buf, p + test_offset, len );
455 test_offset += len;
456 return( 0 );
457}
458
Paul Bakker7dc4c442014-02-01 22:50:26 +0100459#define CHK( c ) if( (c) != 0 ) \
460 { \
461 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462 mbedtls_printf( "failed\n" ); \
Paul Bakker7dc4c442014-02-01 22:50:26 +0100463 return( 1 ); \
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100464 }
465
466/*
467 * Checkup routine for HMAC_DRBG with SHA-1
468 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200469int mbedtls_hmac_drbg_self_test( int verbose )
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100470{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200471 mbedtls_hmac_drbg_context ctx;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100472 unsigned char buf[OUTPUT_LEN];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200473 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100474
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200475 mbedtls_hmac_drbg_init( &ctx );
476
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100477 /*
478 * PR = True
479 */
480 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 mbedtls_printf( " HMAC_DRBG (PR = True) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100482
483 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200484 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000485 hmac_drbg_self_test_entropy, (void *) entropy_pr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100486 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200487 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
488 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
489 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100490 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200491 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100492
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100493 mbedtls_hmac_drbg_free( &ctx );
494
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100495 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200496 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100497
498 /*
499 * PR = False
500 */
501 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200502 mbedtls_printf( " HMAC_DRBG (PR = False) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100503
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100504 mbedtls_hmac_drbg_init( &ctx );
505
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100506 test_offset = 0;
Manuel Pégourié-Gonnardf9e94812015-04-28 22:07:14 +0200507 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000508 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100509 NULL, 0 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200510 CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
511 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
512 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100513 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200514 mbedtls_hmac_drbg_free( &ctx );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100515
Manuel Pégourié-Gonnard0a4fb092015-05-07 12:50:31 +0100516 mbedtls_hmac_drbg_free( &ctx );
517
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100518 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200519 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100520
521 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200522 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100523
524 return( 0 );
525}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200526#endif /* MBEDTLS_SHA1_C */
527#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100528
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200529#endif /* MBEDTLS_HMAC_DRBG_C */