blob: 2e4b682b60f87a816e62f3d56a0c7dd9ade43818 [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é-Gonnarda658a402015-01-23 09:45:19 +00004 * Copyright (C) 2014, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +01005 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +00006 * This file is part of mbed TLS (https://tls.mbed.org)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +01007 *
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +01008 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
23/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010024 * The NIST SP 800-90A DRBGs are described in the following publication.
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010025 * http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010026 * References below are based on rev. 1 (January 2012).
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010027 */
28
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020029#if !defined(POLARSSL_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000030#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020031#else
32#include POLARSSL_CONFIG_FILE
33#endif
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010034
35#if defined(POLARSSL_HMAC_DRBG_C)
36
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000037#include "mbedtls/hmac_drbg.h"
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010038
Rich Evans00ab4702015-02-06 13:43:58 +000039#include <string.h>
40
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +010041#if defined(POLARSSL_FS_IO)
42#include <stdio.h>
43#endif
44
Rich Evans00ab4702015-02-06 13:43:58 +000045#if defined(POLARSSL_SELF_TEST)
Paul Bakker7dc4c442014-02-01 22:50:26 +010046#if defined(POLARSSL_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000047#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010048#else
Rich Evans00ab4702015-02-06 13:43:58 +000049#include <stdio.h>
Paul Bakker7dc4c442014-02-01 22:50:26 +010050#define polarssl_printf printf
Rich Evans00ab4702015-02-06 13:43:58 +000051#endif /* POLARSSL_SELF_TEST */
52#endif /* POLARSSL_PLATFORM_C */
Paul Bakker7dc4c442014-02-01 22:50:26 +010053
Paul Bakker34617722014-06-13 17:20:13 +020054/* Implementation that should never be optimized out by the compiler */
55static void polarssl_zeroize( void *v, size_t n ) {
56 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
57}
58
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010059/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010060 * HMAC_DRBG update, using optional additional data (10.1.2.2)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010061 */
62void hmac_drbg_update( hmac_drbg_context *ctx,
63 const unsigned char *additional, size_t add_len )
64{
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +010065 size_t md_len = md_get_size( ctx->md_ctx.md_info );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010066 unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
67 unsigned char sep[1];
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +010068 unsigned char K[POLARSSL_MD_MAX_SIZE];
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010069
70 for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
71 {
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010072 /* Step 1 or 4 */
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +010073 md_hmac_reset( &ctx->md_ctx );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010074 md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
75 md_hmac_update( &ctx->md_ctx, sep, 1 );
76 if( rounds == 2 )
77 md_hmac_update( &ctx->md_ctx, additional, add_len );
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +010078 md_hmac_finish( &ctx->md_ctx, K );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010079
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010080 /* Step 2 or 5 */
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +010081 md_hmac_starts( &ctx->md_ctx, K, md_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010082 md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
83 md_hmac_finish( &ctx->md_ctx, ctx->V );
84 }
85}
86
87/*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +010088 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010089 */
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +010090int hmac_drbg_init_buf( hmac_drbg_context *ctx,
91 const md_info_t * md_info,
92 const unsigned char *data, size_t data_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010093{
94 int ret;
95
96 memset( ctx, 0, sizeof( hmac_drbg_context ) );
97
Paul Bakker84bbeb52014-07-01 14:53:22 +020098 md_init( &ctx->md_ctx );
99
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100100 if( ( ret = md_init_ctx( &ctx->md_ctx, md_info ) ) != 0 )
101 return( ret );
102
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100103 /*
104 * Set initial working state.
105 * Use the V memory location, which is currently all 0, to initialize the
106 * MD context with an all-zero key. Then set V to its initial value.
107 */
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100108 md_hmac_starts( &ctx->md_ctx, ctx->V, md_get_size( md_info ) );
109 memset( ctx->V, 0x01, md_get_size( md_info ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100110
111 hmac_drbg_update( ctx, data, data_len );
112
113 return( 0 );
114}
115
116/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100117 * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100118 */
119int hmac_drbg_reseed( hmac_drbg_context *ctx,
120 const unsigned char *additional, size_t len )
121{
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100122 unsigned char seed[POLARSSL_HMAC_DRBG_MAX_SEED_INPUT];
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100123 size_t seedlen;
124
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100125 /* III. Check input length */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100126 if( len > POLARSSL_HMAC_DRBG_MAX_INPUT ||
127 ctx->entropy_len + len > POLARSSL_HMAC_DRBG_MAX_SEED_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100128 {
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100129 return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100130 }
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100131
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100132 memset( seed, 0, POLARSSL_HMAC_DRBG_MAX_SEED_INPUT );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100133
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100134 /* IV. Gather entropy_len bytes of entropy for the seed */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100135 if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 )
136 return( POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
137
138 seedlen = ctx->entropy_len;
139
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100140 /* 1. Concatenate entropy and additional data if any */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100141 if( additional != NULL && len != 0 )
142 {
143 memcpy( seed + seedlen, additional, len );
144 seedlen += len;
145 }
146
147 /* 2. Update state */
148 hmac_drbg_update( ctx, seed, seedlen );
149
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100150 /* 3. Reset reseed_counter */
151 ctx->reseed_counter = 1;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100152
153 /* 4. Done */
154 return( 0 );
155}
156
157/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100158 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100159 */
160int hmac_drbg_init( hmac_drbg_context *ctx,
161 const md_info_t * md_info,
162 int (*f_entropy)(void *, unsigned char *, size_t),
163 void *p_entropy,
164 const unsigned char *custom,
165 size_t len )
166{
167 int ret;
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100168 size_t entropy_len, md_size;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100169
170 memset( ctx, 0, sizeof( hmac_drbg_context ) );
171
Paul Bakker84bbeb52014-07-01 14:53:22 +0200172 md_init( &ctx->md_ctx );
173
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100174 if( ( ret = md_init_ctx( &ctx->md_ctx, md_info ) ) != 0 )
175 return( ret );
176
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100177 md_size = md_get_size( md_info );
178
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100179 /*
180 * Set initial working state.
181 * Use the V memory location, which is currently all 0, to initialize the
182 * MD context with an all-zero key. Then set V to its initial value.
183 */
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100184 md_hmac_starts( &ctx->md_ctx, ctx->V, md_size );
185 memset( ctx->V, 0x01, md_size );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100186
187 ctx->f_entropy = f_entropy;
188 ctx->p_entropy = p_entropy;
189
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100190 ctx->reseed_interval = POLARSSL_HMAC_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100191
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100192 /*
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100193 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
194 * each hash function, then according to SP800-90A rev1 10.1 table 2,
195 * min_entropy_len (in bits) is security_strength.
196 *
197 * (This also matches the sizes used in the NIST test vectors.)
198 */
Manuel Pégourié-Gonnardca878db2015-03-24 12:13:30 +0100199 entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
200 md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
201 32; /* better (256+) -> 256 bits */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100202
203 /*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100204 * For initialisation, use more entropy to emulate a nonce
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100205 * (Again, matches test vectors.)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100206 */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100207 ctx->entropy_len = entropy_len * 3 / 2;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100208
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100209 if( ( ret = hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
210 return( ret );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100211
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100212 ctx->entropy_len = entropy_len;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100213
214 return( 0 );
215}
216
217/*
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100218 * Set prediction resistance
219 */
220void hmac_drbg_set_prediction_resistance( hmac_drbg_context *ctx,
221 int resistance )
222{
223 ctx->prediction_resistance = resistance;
224}
225
226/*
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100227 * Set entropy length grabbed for reseeds
228 */
229void hmac_drbg_set_entropy_len( hmac_drbg_context *ctx, size_t len )
230{
231 ctx->entropy_len = len;
232}
233
234/*
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100235 * Set reseed interval
236 */
237void hmac_drbg_set_reseed_interval( hmac_drbg_context *ctx, int interval )
238{
239 ctx->reseed_interval = interval;
240}
241
242/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100243 * HMAC_DRBG random function with optional additional data:
244 * 10.1.2.5 (arabic) + 9.3 (Roman)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100245 */
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100246int hmac_drbg_random_with_add( void *p_rng,
247 unsigned char *output, size_t out_len,
248 const unsigned char *additional, size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100249{
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100250 int ret;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100251 hmac_drbg_context *ctx = (hmac_drbg_context *) p_rng;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100252 size_t md_len = md_get_size( ctx->md_ctx.md_info );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100253 size_t left = out_len;
254 unsigned char *out = output;
255
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100256 /* II. Check request length */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100257 if( out_len > POLARSSL_HMAC_DRBG_MAX_REQUEST )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100258 return( POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
259
260 /* III. Check input length */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100261 if( add_len > POLARSSL_HMAC_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100262 return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
263
264 /* 1. (aka VII and IX) Check reseed counter and PR */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100265 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
266 ( ctx->prediction_resistance == POLARSSL_HMAC_DRBG_PR_ON ||
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100267 ctx->reseed_counter > ctx->reseed_interval ) )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100268 {
269 if( ( ret = hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
270 return( ret );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100271
272 add_len = 0; /* VII.4 */
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100273 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100274
275 /* 2. Use additional data if any */
276 if( additional != NULL && add_len != 0 )
277 hmac_drbg_update( ctx, additional, add_len );
278
279 /* 3, 4, 5. Generate bytes */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100280 while( left != 0 )
281 {
282 size_t use_len = left > md_len ? md_len : left;
283
Manuel Pégourié-Gonnardd742a032014-01-30 19:07:22 +0100284 md_hmac_reset( &ctx->md_ctx );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100285 md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
286 md_hmac_finish( &ctx->md_ctx, ctx->V );
287
288 memcpy( out, ctx->V, use_len );
289 out += use_len;
290 left -= use_len;
291 }
292
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100293 /* 6. Update */
294 hmac_drbg_update( ctx, additional, add_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100295
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100296 /* 7. Update reseed counter */
297 ctx->reseed_counter++;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100298
299 /* 8. Done */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100300 return( 0 );
301}
302
303/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100304 * HMAC_DRBG random function
305 */
306int hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
307{
308 return( hmac_drbg_random_with_add( p_rng, output, out_len, NULL, 0 ) );
309}
310
311/*
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100312 * Free an HMAC_DRBG context
313 */
314void hmac_drbg_free( hmac_drbg_context *ctx )
315{
316 if( ctx == NULL )
317 return;
318
Manuel Pégourié-Gonnard96583912015-03-20 18:19:32 +0000319 md_free( &ctx->md_ctx );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100320
Paul Bakker34617722014-06-13 17:20:13 +0200321 polarssl_zeroize( ctx, sizeof( hmac_drbg_context ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100322}
323
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100324#if defined(POLARSSL_FS_IO)
325int hmac_drbg_write_seed_file( hmac_drbg_context *ctx, const char *path )
326{
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100327 int ret;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100328 FILE *f;
329 unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ];
330
331 if( ( f = fopen( path, "wb" ) ) == NULL )
332 return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
333
334 if( ( ret = hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
335 goto exit;
336
337 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
338 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100339 ret = POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR;
340 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100341 }
342
343 ret = 0;
344
345exit:
346 fclose( f );
347 return( ret );
348}
349
350int hmac_drbg_update_seed_file( hmac_drbg_context *ctx, const char *path )
351{
352 FILE *f;
353 size_t n;
354 unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ];
355
356 if( ( f = fopen( path, "rb" ) ) == NULL )
357 return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
358
359 fseek( f, 0, SEEK_END );
360 n = (size_t) ftell( f );
361 fseek( f, 0, SEEK_SET );
362
363 if( n > POLARSSL_HMAC_DRBG_MAX_INPUT )
364 {
365 fclose( f );
366 return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
367 }
368
369 if( fread( buf, 1, n, f ) != n )
370 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100371 fclose( f );
372 return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100373 }
374
375 fclose( f );
376
377 hmac_drbg_update( ctx, buf, n );
378
379 return( hmac_drbg_write_seed_file( ctx, path ) );
380}
381#endif /* POLARSSL_FS_IO */
382
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100383
384#if defined(POLARSSL_SELF_TEST)
385
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100386#if !defined(POLARSSL_SHA1_C)
387/* Dummy checkup routine */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100388int hmac_drbg_self_test( int verbose )
389{
390
391 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100392 polarssl_printf( "\n" );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100393
394 return( 0 );
395}
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100396#else
397
398#define OUTPUT_LEN 80
399
400/* From a NIST PR=true test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000401static const unsigned char entropy_pr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100402 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
403 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
404 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
405 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
406 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
407static const unsigned char result_pr[OUTPUT_LEN] = {
408 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
409 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
410 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
411 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
412 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
413 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
414 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
415
416/* From a NIST PR=false test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000417static const unsigned char entropy_nopr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100418 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
419 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
420 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
421 0xe9, 0x9d, 0xfe, 0xdf };
422static const unsigned char result_nopr[OUTPUT_LEN] = {
423 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
424 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
425 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
426 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
427 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
428 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
429 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
430
431/* "Entropy" from buffer */
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100432static size_t test_offset;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100433static int hmac_drbg_self_test_entropy( void *data,
434 unsigned char *buf, size_t len )
435{
436 const unsigned char *p = data;
437 memcpy( buf, p + test_offset, len );
438 test_offset += len;
439 return( 0 );
440}
441
Paul Bakker7dc4c442014-02-01 22:50:26 +0100442#define CHK( c ) if( (c) != 0 ) \
443 { \
444 if( verbose != 0 ) \
445 polarssl_printf( "failed\n" ); \
446 return( 1 ); \
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100447 }
448
449/*
450 * Checkup routine for HMAC_DRBG with SHA-1
451 */
452int hmac_drbg_self_test( int verbose )
453{
454 hmac_drbg_context ctx;
455 unsigned char buf[OUTPUT_LEN];
456 const md_info_t *md_info = md_info_from_type( POLARSSL_MD_SHA1 );
457
458 /*
459 * PR = True
460 */
461 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100462 polarssl_printf( " HMAC_DRBG (PR = True) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100463
464 test_offset = 0;
465 CHK( hmac_drbg_init( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000466 hmac_drbg_self_test_entropy, (void *) entropy_pr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100467 NULL, 0 ) );
468 hmac_drbg_set_prediction_resistance( &ctx, POLARSSL_HMAC_DRBG_PR_ON );
469 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
470 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
471 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
472 hmac_drbg_free( &ctx );
473
474 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100475 polarssl_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100476
477 /*
478 * PR = False
479 */
480 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100481 polarssl_printf( " HMAC_DRBG (PR = False) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100482
483 test_offset = 0;
484 CHK( hmac_drbg_init( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000485 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100486 NULL, 0 ) );
487 CHK( hmac_drbg_reseed( &ctx, NULL, 0 ) );
488 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
489 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
490 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
491 hmac_drbg_free( &ctx );
492
493 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100494 polarssl_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100495
496 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100497 polarssl_printf( "\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100498
499 return( 0 );
500}
501#endif /* POLARSSL_SHA1_C */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100502#endif /* POLARSSL_SELF_TEST */
503
504#endif /* POLARSSL_HMAC_DRBG_C */