blob: cfeb8a4c880137415038af871e55aff95f86ac2f [file] [log] [blame]
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +01001/*
2 * HMAC_DRBG implementation (NIST SP 800-90)
3 *
4 * Copyright (C) 2014, Brainspark B.V.
5 *
6 * This file is part of PolarSSL (http://www.polarssl.org)
7 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
8 *
9 * All rights reserved.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 */
25
26/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010027 * The NIST SP 800-90A DRBGs are described in the following publication.
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010028 * http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010029 * References below are based on rev. 1 (January 2012).
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010030 */
31
32#include "polarssl/config.h"
33
34#if defined(POLARSSL_HMAC_DRBG_C)
35
36#include "polarssl/hmac_drbg.h"
37
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +010038#if defined(POLARSSL_FS_IO)
39#include <stdio.h>
40#endif
41
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010042/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010043 * HMAC_DRBG update, using optional additional data (10.1.2.2)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010044 */
45void hmac_drbg_update( hmac_drbg_context *ctx,
46 const unsigned char *additional, size_t add_len )
47{
48 size_t md_len = ctx->md_ctx.md_info->size;
49 unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
50 unsigned char sep[1];
51
52 for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
53 {
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010054 /* Step 1 or 4 */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010055 md_hmac_starts( &ctx->md_ctx, ctx->K, md_len );
56 md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
57 md_hmac_update( &ctx->md_ctx, sep, 1 );
58 if( rounds == 2 )
59 md_hmac_update( &ctx->md_ctx, additional, add_len );
60 md_hmac_finish( &ctx->md_ctx, ctx->K );
61
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010062 /* Step 2 or 5 */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010063 md_hmac_starts( &ctx->md_ctx, ctx->K, md_len );
64 md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
65 md_hmac_finish( &ctx->md_ctx, ctx->V );
66 }
67}
68
69/*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +010070 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010071 */
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +010072int hmac_drbg_init_buf( hmac_drbg_context *ctx,
73 const md_info_t * md_info,
74 const unsigned char *data, size_t data_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010075{
76 int ret;
77
78 memset( ctx, 0, sizeof( hmac_drbg_context ) );
79
80 if( ( ret = md_init_ctx( &ctx->md_ctx, md_info ) ) != 0 )
81 return( ret );
82
83 memset( ctx->V, 0x01, md_info->size );
84 /* ctx->K is already 0 */
85
86 hmac_drbg_update( ctx, data, data_len );
87
88 return( 0 );
89}
90
91/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +010092 * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +010093 */
94int hmac_drbg_reseed( hmac_drbg_context *ctx,
95 const unsigned char *additional, size_t len )
96{
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +010097 unsigned char seed[POLARSSL_HMAC_DRBG_MAX_SEED_INPUT];
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +010098 size_t seedlen;
99
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100100 /* III. Check input length */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100101 if( len > POLARSSL_HMAC_DRBG_MAX_INPUT ||
102 ctx->entropy_len + len > POLARSSL_HMAC_DRBG_MAX_SEED_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100103 {
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100104 return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100105 }
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100106
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100107 memset( seed, 0, POLARSSL_HMAC_DRBG_MAX_SEED_INPUT );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100108
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100109 /* IV. Gather entropy_len bytes of entropy for the seed */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100110 if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 )
111 return( POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
112
113 seedlen = ctx->entropy_len;
114
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100115 /* 1. Concatenate entropy and additional data if any */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100116 if( additional != NULL && len != 0 )
117 {
118 memcpy( seed + seedlen, additional, len );
119 seedlen += len;
120 }
121
122 /* 2. Update state */
123 hmac_drbg_update( ctx, seed, seedlen );
124
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100125 /* 3. Reset reseed_counter */
126 ctx->reseed_counter = 1;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100127
128 /* 4. Done */
129 return( 0 );
130}
131
132/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100133 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100134 */
135int hmac_drbg_init( hmac_drbg_context *ctx,
136 const md_info_t * md_info,
137 int (*f_entropy)(void *, unsigned char *, size_t),
138 void *p_entropy,
139 const unsigned char *custom,
140 size_t len )
141{
142 int ret;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100143 size_t entropy_len;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100144
145 memset( ctx, 0, sizeof( hmac_drbg_context ) );
146
147 if( ( ret = md_init_ctx( &ctx->md_ctx, md_info ) ) != 0 )
148 return( ret );
149
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100150 /* Set initial working state */
151 memset( ctx->V, 0x01, md_info->size );
152 /* ctx->K is already 0 */
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100153
154 ctx->f_entropy = f_entropy;
155 ctx->p_entropy = p_entropy;
156
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100157 ctx->reseed_interval = POLARSSL_HMAC_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100158
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100159 /*
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100160 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
161 * each hash function, then according to SP800-90A rev1 10.1 table 2,
162 * min_entropy_len (in bits) is security_strength.
163 *
164 * (This also matches the sizes used in the NIST test vectors.)
165 */
166 entropy_len = md_info->size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
167 md_info->size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
168 32; /* better (256+) -> 256 bits */
169
170 /*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100171 * For initialisation, use more entropy to emulate a nonce
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100172 * (Again, matches test vectors.)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100173 */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100174 ctx->entropy_len = entropy_len * 3 / 2;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100175
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100176 if( ( ret = hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
177 return( ret );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100178
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100179 ctx->entropy_len = entropy_len;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100180
181 return( 0 );
182}
183
184/*
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100185 * Set prediction resistance
186 */
187void hmac_drbg_set_prediction_resistance( hmac_drbg_context *ctx,
188 int resistance )
189{
190 ctx->prediction_resistance = resistance;
191}
192
193/*
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100194 * Set entropy length grabbed for reseeds
195 */
196void hmac_drbg_set_entropy_len( hmac_drbg_context *ctx, size_t len )
197{
198 ctx->entropy_len = len;
199}
200
201/*
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100202 * Set reseed interval
203 */
204void hmac_drbg_set_reseed_interval( hmac_drbg_context *ctx, int interval )
205{
206 ctx->reseed_interval = interval;
207}
208
209/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100210 * HMAC_DRBG random function with optional additional data:
211 * 10.1.2.5 (arabic) + 9.3 (Roman)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100212 */
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100213int hmac_drbg_random_with_add( void *p_rng,
214 unsigned char *output, size_t out_len,
215 const unsigned char *additional, size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100216{
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100217 int ret;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100218 hmac_drbg_context *ctx = (hmac_drbg_context *) p_rng;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100219 size_t md_len = md_get_size( ctx->md_ctx.md_info );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100220 size_t left = out_len;
221 unsigned char *out = output;
222
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100223 /* II. Check request length */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100224 if( out_len > POLARSSL_HMAC_DRBG_MAX_REQUEST )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100225 return( POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
226
227 /* III. Check input length */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100228 if( add_len > POLARSSL_HMAC_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100229 return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
230
231 /* 1. (aka VII and IX) Check reseed counter and PR */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100232 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
233 ( ctx->prediction_resistance == POLARSSL_HMAC_DRBG_PR_ON ||
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100234 ctx->reseed_counter > ctx->reseed_interval ) )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100235 {
236 if( ( ret = hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
237 return( ret );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100238
239 add_len = 0; /* VII.4 */
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100240 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100241
242 /* 2. Use additional data if any */
243 if( additional != NULL && add_len != 0 )
244 hmac_drbg_update( ctx, additional, add_len );
245
246 /* 3, 4, 5. Generate bytes */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100247 while( left != 0 )
248 {
249 size_t use_len = left > md_len ? md_len : left;
250
Manuel Pégourié-Gonnardd742a032014-01-30 19:07:22 +0100251 md_hmac_reset( &ctx->md_ctx );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100252 md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
253 md_hmac_finish( &ctx->md_ctx, ctx->V );
254
255 memcpy( out, ctx->V, use_len );
256 out += use_len;
257 left -= use_len;
258 }
259
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100260 /* 6. Update */
261 hmac_drbg_update( ctx, additional, add_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100262
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100263 /* 7. Update reseed counter */
264 ctx->reseed_counter++;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100265
266 /* 8. Done */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100267 return( 0 );
268}
269
270/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100271 * HMAC_DRBG random function
272 */
273int hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
274{
275 return( hmac_drbg_random_with_add( p_rng, output, out_len, NULL, 0 ) );
276}
277
278/*
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100279 * Free an HMAC_DRBG context
280 */
281void hmac_drbg_free( hmac_drbg_context *ctx )
282{
283 if( ctx == NULL )
284 return;
285
286 md_free_ctx( &ctx->md_ctx );
287
288 memset( ctx, 0, sizeof( hmac_drbg_context ) );
289}
290
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100291#if defined(POLARSSL_FS_IO)
292int hmac_drbg_write_seed_file( hmac_drbg_context *ctx, const char *path )
293{
294 int ret = POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR;
295 FILE *f;
296 unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ];
297
298 if( ( f = fopen( path, "wb" ) ) == NULL )
299 return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
300
301 if( ( ret = hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
302 goto exit;
303
304 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
305 {
306 ret = POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR;
307 goto exit;
308 }
309
310 ret = 0;
311
312exit:
313 fclose( f );
314 return( ret );
315}
316
317int hmac_drbg_update_seed_file( hmac_drbg_context *ctx, const char *path )
318{
319 FILE *f;
320 size_t n;
321 unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ];
322
323 if( ( f = fopen( path, "rb" ) ) == NULL )
324 return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
325
326 fseek( f, 0, SEEK_END );
327 n = (size_t) ftell( f );
328 fseek( f, 0, SEEK_SET );
329
330 if( n > POLARSSL_HMAC_DRBG_MAX_INPUT )
331 {
332 fclose( f );
333 return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
334 }
335
336 if( fread( buf, 1, n, f ) != n )
337 {
338 fclose( f );
339 return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
340 }
341
342 fclose( f );
343
344 hmac_drbg_update( ctx, buf, n );
345
346 return( hmac_drbg_write_seed_file( ctx, path ) );
347}
348#endif /* POLARSSL_FS_IO */
349
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100350
351#if defined(POLARSSL_SELF_TEST)
352
353#include <stdio.h>
354
355/*
356 * Checkup routine
357 */
358int hmac_drbg_self_test( int verbose )
359{
360
361 if( verbose != 0 )
362 printf( "\n" );
363
364 return( 0 );
365}
366#endif /* POLARSSL_SELF_TEST */
367
368#endif /* POLARSSL_HMAC_DRBG_C */