PolarSSL v1.3.9
hmac_drbg.c
Go to the documentation of this file.
1/*
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/*
27 * The NIST SP 800-90A DRBGs are described in the following publication.
28 * http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
29 * References below are based on rev. 1 (January 2012).
30 */
31
32#if !defined(POLARSSL_CONFIG_FILE)
33#include "polarssl/config.h"
34#else
35#include POLARSSL_CONFIG_FILE
36#endif
37
38#if defined(POLARSSL_HMAC_DRBG_C)
39
40#include "polarssl/hmac_drbg.h"
41
42#if defined(POLARSSL_FS_IO)
43#include <stdio.h>
44#endif
45
46#if defined(POLARSSL_PLATFORM_C)
47#include "polarssl/platform.h"
48#else
49#define polarssl_printf printf
50#endif
51
52/* Implementation that should never be optimized out by the compiler */
53static void polarssl_zeroize( void *v, size_t n ) {
54 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
55}
56
57/*
58 * HMAC_DRBG update, using optional additional data (10.1.2.2)
59 */
61 const unsigned char *additional, size_t add_len )
62{
63 size_t md_len = ctx->md_ctx.md_info->size;
64 unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
65 unsigned char sep[1];
66 unsigned char K[POLARSSL_MD_MAX_SIZE];
67
68 for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
69 {
70 /* Step 1 or 4 */
71 md_hmac_reset( &ctx->md_ctx );
72 md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
73 md_hmac_update( &ctx->md_ctx, sep, 1 );
74 if( rounds == 2 )
75 md_hmac_update( &ctx->md_ctx, additional, add_len );
76 md_hmac_finish( &ctx->md_ctx, K );
77
78 /* Step 2 or 5 */
79 md_hmac_starts( &ctx->md_ctx, K, md_len );
80 md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
81 md_hmac_finish( &ctx->md_ctx, ctx->V );
82 }
83}
84
85/*
86 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
87 */
89 const md_info_t * md_info,
90 const unsigned char *data, size_t data_len )
91{
92 int ret;
93
94 memset( ctx, 0, sizeof( hmac_drbg_context ) );
95
96 md_init( &ctx->md_ctx );
97
98 if( ( ret = md_init_ctx( &ctx->md_ctx, md_info ) ) != 0 )
99 return( ret );
100
101 /*
102 * Set initial working state.
103 * Use the V memory location, which is currently all 0, to initialize the
104 * MD context with an all-zero key. Then set V to its initial value.
105 */
106 md_hmac_starts( &ctx->md_ctx, ctx->V, md_info->size );
107 memset( ctx->V, 0x01, md_info->size );
108
109 hmac_drbg_update( ctx, data, data_len );
110
111 return( 0 );
112}
113
114/*
115 * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
116 */
118 const unsigned char *additional, size_t len )
119{
120 unsigned char seed[POLARSSL_HMAC_DRBG_MAX_SEED_INPUT];
121 size_t seedlen;
122
123 /* III. Check input length */
126 {
128 }
129
130 memset( seed, 0, POLARSSL_HMAC_DRBG_MAX_SEED_INPUT );
131
132 /* IV. Gather entropy_len bytes of entropy for the seed */
133 if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 )
135
136 seedlen = ctx->entropy_len;
137
138 /* 1. Concatenate entropy and additional data if any */
139 if( additional != NULL && len != 0 )
140 {
141 memcpy( seed + seedlen, additional, len );
142 seedlen += len;
143 }
144
145 /* 2. Update state */
146 hmac_drbg_update( ctx, seed, seedlen );
147
148 /* 3. Reset reseed_counter */
149 ctx->reseed_counter = 1;
150
151 /* 4. Done */
152 return( 0 );
153}
154
155/*
156 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
157 */
159 const md_info_t * md_info,
160 int (*f_entropy)(void *, unsigned char *, size_t),
161 void *p_entropy,
162 const unsigned char *custom,
163 size_t len )
164{
165 int ret;
166 size_t entropy_len;
167
168 memset( ctx, 0, sizeof( hmac_drbg_context ) );
169
170 md_init( &ctx->md_ctx );
171
172 if( ( ret = md_init_ctx( &ctx->md_ctx, md_info ) ) != 0 )
173 return( ret );
174
175 /*
176 * Set initial working state.
177 * Use the V memory location, which is currently all 0, to initialize the
178 * MD context with an all-zero key. Then set V to its initial value.
179 */
180 md_hmac_starts( &ctx->md_ctx, ctx->V, md_info->size );
181 memset( ctx->V, 0x01, md_info->size );
182
183 ctx->f_entropy = f_entropy;
184 ctx->p_entropy = p_entropy;
185
187
188 /*
189 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
190 * each hash function, then according to SP800-90A rev1 10.1 table 2,
191 * min_entropy_len (in bits) is security_strength.
192 *
193 * (This also matches the sizes used in the NIST test vectors.)
194 */
195 entropy_len = md_info->size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
196 md_info->size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
197 32; /* better (256+) -> 256 bits */
198
199 /*
200 * For initialisation, use more entropy to emulate a nonce
201 * (Again, matches test vectors.)
202 */
203 ctx->entropy_len = entropy_len * 3 / 2;
204
205 if( ( ret = hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
206 return( ret );
207
208 ctx->entropy_len = entropy_len;
209
210 return( 0 );
211}
212
213/*
214 * Set prediction resistance
215 */
217 int resistance )
218{
219 ctx->prediction_resistance = resistance;
220}
221
222/*
223 * Set entropy length grabbed for reseeds
224 */
225void hmac_drbg_set_entropy_len( hmac_drbg_context *ctx, size_t len )
226{
227 ctx->entropy_len = len;
228}
229
230/*
231 * Set reseed interval
232 */
233void hmac_drbg_set_reseed_interval( hmac_drbg_context *ctx, int interval )
234{
235 ctx->reseed_interval = interval;
236}
237
238/*
239 * HMAC_DRBG random function with optional additional data:
240 * 10.1.2.5 (arabic) + 9.3 (Roman)
241 */
242int hmac_drbg_random_with_add( void *p_rng,
243 unsigned char *output, size_t out_len,
244 const unsigned char *additional, size_t add_len )
245{
246 int ret;
247 hmac_drbg_context *ctx = (hmac_drbg_context *) p_rng;
248 size_t md_len = md_get_size( ctx->md_ctx.md_info );
249 size_t left = out_len;
250 unsigned char *out = output;
251
252 /* II. Check request length */
253 if( out_len > POLARSSL_HMAC_DRBG_MAX_REQUEST )
255
256 /* III. Check input length */
257 if( add_len > POLARSSL_HMAC_DRBG_MAX_INPUT )
259
260 /* 1. (aka VII and IX) Check reseed counter and PR */
261 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
263 ctx->reseed_counter > ctx->reseed_interval ) )
264 {
265 if( ( ret = hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
266 return( ret );
267
268 add_len = 0; /* VII.4 */
269 }
270
271 /* 2. Use additional data if any */
272 if( additional != NULL && add_len != 0 )
273 hmac_drbg_update( ctx, additional, add_len );
274
275 /* 3, 4, 5. Generate bytes */
276 while( left != 0 )
277 {
278 size_t use_len = left > md_len ? md_len : left;
279
280 md_hmac_reset( &ctx->md_ctx );
281 md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
282 md_hmac_finish( &ctx->md_ctx, ctx->V );
283
284 memcpy( out, ctx->V, use_len );
285 out += use_len;
286 left -= use_len;
287 }
288
289 /* 6. Update */
290 hmac_drbg_update( ctx, additional, add_len );
291
292 /* 7. Update reseed counter */
293 ctx->reseed_counter++;
294
295 /* 8. Done */
296 return( 0 );
297}
298
299/*
300 * HMAC_DRBG random function
301 */
302int hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
303{
304 return( hmac_drbg_random_with_add( p_rng, output, out_len, NULL, 0 ) );
305}
306
307/*
308 * Free an HMAC_DRBG context
309 */
311{
312 if( ctx == NULL )
313 return;
314
315 md_free_ctx( &ctx->md_ctx );
316
317 polarssl_zeroize( ctx, sizeof( hmac_drbg_context ) );
318}
319
320#if defined(POLARSSL_FS_IO)
321int hmac_drbg_write_seed_file( hmac_drbg_context *ctx, const char *path )
322{
323 int ret;
324 FILE *f;
325 unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ];
326
327 if( ( f = fopen( path, "wb" ) ) == NULL )
329
330 if( ( ret = hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
331 goto exit;
332
333 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
334 {
336 goto exit;
337 }
338
339 ret = 0;
340
341exit:
342 fclose( f );
343 return( ret );
344}
345
346int hmac_drbg_update_seed_file( hmac_drbg_context *ctx, const char *path )
347{
348 FILE *f;
349 size_t n;
350 unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ];
351
352 if( ( f = fopen( path, "rb" ) ) == NULL )
354
355 fseek( f, 0, SEEK_END );
356 n = (size_t) ftell( f );
357 fseek( f, 0, SEEK_SET );
358
360 {
361 fclose( f );
363 }
364
365 if( fread( buf, 1, n, f ) != n )
366 {
367 fclose( f );
369 }
370
371 fclose( f );
372
373 hmac_drbg_update( ctx, buf, n );
374
375 return( hmac_drbg_write_seed_file( ctx, path ) );
376}
377#endif /* POLARSSL_FS_IO */
378
379
380#if defined(POLARSSL_SELF_TEST)
381
382#include <stdio.h>
383
384#if !defined(POLARSSL_SHA1_C)
385/* Dummy checkup routine */
386int hmac_drbg_self_test( int verbose )
387{
388
389 if( verbose != 0 )
390 polarssl_printf( "\n" );
391
392 return( 0 );
393}
394#else
395
396#define OUTPUT_LEN 80
397
398/* From a NIST PR=true test vector */
399static unsigned char entropy_pr[] = {
400 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
401 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
402 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
403 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
404 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
405static const unsigned char result_pr[OUTPUT_LEN] = {
406 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
407 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
408 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
409 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
410 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
411 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
412 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
413
414/* From a NIST PR=false test vector */
415static unsigned char entropy_nopr[] = {
416 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
417 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
418 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
419 0xe9, 0x9d, 0xfe, 0xdf };
420static const unsigned char result_nopr[OUTPUT_LEN] = {
421 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
422 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
423 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
424 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
425 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
426 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
427 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
428
429/* "Entropy" from buffer */
430static size_t test_offset;
431static int hmac_drbg_self_test_entropy( void *data,
432 unsigned char *buf, size_t len )
433{
434 const unsigned char *p = data;
435 memcpy( buf, p + test_offset, len );
436 test_offset += len;
437 return( 0 );
438}
439
440#define CHK( c ) if( (c) != 0 ) \
441 { \
442 if( verbose != 0 ) \
443 polarssl_printf( "failed\n" ); \
444 return( 1 ); \
445 }
446
447/*
448 * Checkup routine for HMAC_DRBG with SHA-1
449 */
450int hmac_drbg_self_test( int verbose )
451{
453 unsigned char buf[OUTPUT_LEN];
454 const md_info_t *md_info = md_info_from_type( POLARSSL_MD_SHA1 );
455
456 /*
457 * PR = True
458 */
459 if( verbose != 0 )
460 polarssl_printf( " HMAC_DRBG (PR = True) : " );
461
462 test_offset = 0;
463 CHK( hmac_drbg_init( &ctx, md_info,
464 hmac_drbg_self_test_entropy, entropy_pr,
465 NULL, 0 ) );
467 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
468 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
469 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
470 hmac_drbg_free( &ctx );
471
472 if( verbose != 0 )
473 polarssl_printf( "passed\n" );
474
475 /*
476 * PR = False
477 */
478 if( verbose != 0 )
479 polarssl_printf( " HMAC_DRBG (PR = False) : " );
480
481 test_offset = 0;
482 CHK( hmac_drbg_init( &ctx, md_info,
483 hmac_drbg_self_test_entropy, entropy_nopr,
484 NULL, 0 ) );
485 CHK( hmac_drbg_reseed( &ctx, NULL, 0 ) );
486 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
487 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
488 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
489 hmac_drbg_free( &ctx );
490
491 if( verbose != 0 )
492 polarssl_printf( "passed\n" );
493
494 if( verbose != 0 )
495 polarssl_printf( "\n" );
496
497 return( 0 );
498}
499#endif /* POLARSSL_SHA1_C */
500#endif /* POLARSSL_SELF_TEST */
501
502#endif /* POLARSSL_HMAC_DRBG_C */
Configuration options (set of defines)
HMAC_DRBG (NIST SP 800-90A)
#define POLARSSL_HMAC_DRBG_MAX_SEED_INPUT
Maximum size of (re)seed buffer.
Definition hmac_drbg.h:61
#define POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
The entropy source failed.
Definition hmac_drbg.h:38
void hmac_drbg_set_entropy_len(hmac_drbg_context *ctx, size_t len)
Set the amount of entropy grabbed on each reseed (Default: given by the security strength,...
void hmac_drbg_free(hmac_drbg_context *ctx)
Free an HMAC_DRBG context.
#define POLARSSL_HMAC_DRBG_PR_ON
Prediction resistance enabled
Definition hmac_drbg.h:67
#define POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG
Too many random requested in single call.
Definition hmac_drbg.h:35
#define POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG
Input too large (Entropy + additional).
Definition hmac_drbg.h:36
#define POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR
Read/write error in file.
Definition hmac_drbg.h:37
#define POLARSSL_HMAC_DRBG_MAX_REQUEST
Maximum number of requested bytes per call.
Definition hmac_drbg.h:57
int hmac_drbg_reseed(hmac_drbg_context *ctx, const unsigned char *additional, size_t len)
HMAC_DRBG reseeding (extracts data from entropy source)
int hmac_drbg_init(hmac_drbg_context *ctx, const md_info_t *md_info, int(*f_entropy)(void *, unsigned char *, size_t), void *p_entropy, const unsigned char *custom, size_t len)
HMAC_DRBG initialisation.
#define POLARSSL_HMAC_DRBG_RESEED_INTERVAL
Interval before reseed is performed by default.
Definition hmac_drbg.h:49
void hmac_drbg_set_prediction_resistance(hmac_drbg_context *ctx, int resistance)
Enable / disable prediction resistance (Default: Off)
int hmac_drbg_random(void *p_rng, unsigned char *output, size_t out_len)
HMAC_DRBG generate random.
int hmac_drbg_init_buf(hmac_drbg_context *ctx, const md_info_t *md_info, const unsigned char *data, size_t data_len)
Initilisation of simpified HMAC_DRBG (never reseeds).
#define POLARSSL_HMAC_DRBG_MAX_INPUT
Maximum number of additional input bytes.
Definition hmac_drbg.h:53
int hmac_drbg_random_with_add(void *p_rng, unsigned char *output, size_t output_len, const unsigned char *additional, size_t add_len)
HMAC_DRBG generate random with additional update input.
void hmac_drbg_set_reseed_interval(hmac_drbg_context *ctx, int interval)
Set the reseed interval (Default: POLARSSL_HMAC_DRBG_RESEED_INTERVAL)
void hmac_drbg_update(hmac_drbg_context *ctx, const unsigned char *additional, size_t add_len)
HMAC_DRBG update state.
int md_hmac_reset(md_context_t *ctx)
Generic HMAC context reset.
int md_free_ctx(md_context_t *ctx)
Free the message-specific context of ctx.
#define POLARSSL_MD_MAX_SIZE
Definition md.h:67
static unsigned char md_get_size(const md_info_t *md_info)
Returns the size of the message digest output.
Definition md.h:225
const md_info_t * md_info_from_type(md_type_t md_type)
Returns the message digest information associated with the given digest type.
int md_hmac_update(md_context_t *ctx, const unsigned char *input, size_t ilen)
Generic HMAC process buffer.
int md_init_ctx(md_context_t *ctx, const md_info_t *md_info)
Initialises and fills the message digest context structure with the appropriate values.
int md_hmac_starts(md_context_t *ctx, const unsigned char *key, size_t keylen)
Generic HMAC context setup.
int md_hmac_finish(md_context_t *ctx, unsigned char *output)
Generic HMAC final digest.
void md_init(md_context_t *ctx)
Initialize a md_context (as NONE)
@ POLARSSL_MD_SHA1
Definition md.h:56
PolarSSL Platform abstraction layer.
HMAC_DRBG context.
Definition hmac_drbg.h:77
unsigned char V[POLARSSL_MD_MAX_SIZE]
Definition hmac_drbg.h:81
md_context_t md_ctx
Definition hmac_drbg.h:80
int prediction_resistance
Definition hmac_drbg.h:86
int(* f_entropy)(void *, unsigned char *, size_t)
Definition hmac_drbg.h:91
const md_info_t * md_info
Information about the associated message digest.
Definition md.h:134
Message digest information.
Definition md.h:74
int size
Output length of the digest function.
Definition md.h:82
#define polarssl_printf