blob: eece38997c25788cfbbf1e9dd75306d9935c26a9 [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é-Gonnard490bdf32014-01-27 14:03:10 +010030#include "polarssl/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
37#include "polarssl/hmac_drbg.h"
38
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)
47#include "polarssl/platform.h"
48#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{
65 size_t md_len = ctx->md_ctx.md_info->size;
66 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 */
108 md_hmac_starts( &ctx->md_ctx, ctx->V, md_info->size );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100109 memset( ctx->V, 0x01, md_info->size );
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é-Gonnard8fc484d2014-01-30 18:28:09 +0100168 size_t entropy_len;
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é-Gonnardb05db2a2014-02-01 11:38:05 +0100177 /*
178 * Set initial working state.
179 * Use the V memory location, which is currently all 0, to initialize the
180 * MD context with an all-zero key. Then set V to its initial value.
181 */
182 md_hmac_starts( &ctx->md_ctx, ctx->V, md_info->size );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100183 memset( ctx->V, 0x01, md_info->size );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100184
185 ctx->f_entropy = f_entropy;
186 ctx->p_entropy = p_entropy;
187
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100188 ctx->reseed_interval = POLARSSL_HMAC_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100189
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100190 /*
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100191 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
192 * each hash function, then according to SP800-90A rev1 10.1 table 2,
193 * min_entropy_len (in bits) is security_strength.
194 *
195 * (This also matches the sizes used in the NIST test vectors.)
196 */
197 entropy_len = md_info->size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
198 md_info->size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
199 32; /* better (256+) -> 256 bits */
200
201 /*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100202 * For initialisation, use more entropy to emulate a nonce
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100203 * (Again, matches test vectors.)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100204 */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100205 ctx->entropy_len = entropy_len * 3 / 2;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100206
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100207 if( ( ret = hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
208 return( ret );
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;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100211
212 return( 0 );
213}
214
215/*
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100216 * Set prediction resistance
217 */
218void hmac_drbg_set_prediction_resistance( hmac_drbg_context *ctx,
219 int resistance )
220{
221 ctx->prediction_resistance = resistance;
222}
223
224/*
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100225 * Set entropy length grabbed for reseeds
226 */
227void hmac_drbg_set_entropy_len( hmac_drbg_context *ctx, size_t len )
228{
229 ctx->entropy_len = len;
230}
231
232/*
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100233 * Set reseed interval
234 */
235void hmac_drbg_set_reseed_interval( hmac_drbg_context *ctx, int interval )
236{
237 ctx->reseed_interval = interval;
238}
239
240/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100241 * HMAC_DRBG random function with optional additional data:
242 * 10.1.2.5 (arabic) + 9.3 (Roman)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100243 */
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100244int hmac_drbg_random_with_add( void *p_rng,
245 unsigned char *output, size_t out_len,
246 const unsigned char *additional, size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100247{
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100248 int ret;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100249 hmac_drbg_context *ctx = (hmac_drbg_context *) p_rng;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100250 size_t md_len = md_get_size( ctx->md_ctx.md_info );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100251 size_t left = out_len;
252 unsigned char *out = output;
253
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100254 /* II. Check request length */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100255 if( out_len > POLARSSL_HMAC_DRBG_MAX_REQUEST )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100256 return( POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
257
258 /* III. Check input length */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100259 if( add_len > POLARSSL_HMAC_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100260 return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
261
262 /* 1. (aka VII and IX) Check reseed counter and PR */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100263 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
264 ( ctx->prediction_resistance == POLARSSL_HMAC_DRBG_PR_ON ||
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100265 ctx->reseed_counter > ctx->reseed_interval ) )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100266 {
267 if( ( ret = hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
268 return( ret );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100269
270 add_len = 0; /* VII.4 */
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100271 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100272
273 /* 2. Use additional data if any */
274 if( additional != NULL && add_len != 0 )
275 hmac_drbg_update( ctx, additional, add_len );
276
277 /* 3, 4, 5. Generate bytes */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100278 while( left != 0 )
279 {
280 size_t use_len = left > md_len ? md_len : left;
281
Manuel Pégourié-Gonnardd742a032014-01-30 19:07:22 +0100282 md_hmac_reset( &ctx->md_ctx );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100283 md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
284 md_hmac_finish( &ctx->md_ctx, ctx->V );
285
286 memcpy( out, ctx->V, use_len );
287 out += use_len;
288 left -= use_len;
289 }
290
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100291 /* 6. Update */
292 hmac_drbg_update( ctx, additional, add_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100293
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100294 /* 7. Update reseed counter */
295 ctx->reseed_counter++;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100296
297 /* 8. Done */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100298 return( 0 );
299}
300
301/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100302 * HMAC_DRBG random function
303 */
304int hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
305{
306 return( hmac_drbg_random_with_add( p_rng, output, out_len, NULL, 0 ) );
307}
308
309/*
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100310 * Free an HMAC_DRBG context
311 */
312void hmac_drbg_free( hmac_drbg_context *ctx )
313{
314 if( ctx == NULL )
315 return;
316
Manuel Pégourié-Gonnard93952982015-03-20 18:19:32 +0000317 md_free( &ctx->md_ctx );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100318
Paul Bakker34617722014-06-13 17:20:13 +0200319 polarssl_zeroize( ctx, sizeof( hmac_drbg_context ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100320}
321
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100322#if defined(POLARSSL_FS_IO)
323int hmac_drbg_write_seed_file( hmac_drbg_context *ctx, const char *path )
324{
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100325 int ret;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100326 FILE *f;
327 unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ];
328
329 if( ( f = fopen( path, "wb" ) ) == NULL )
330 return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
331
332 if( ( ret = hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
333 goto exit;
334
335 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
336 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100337 ret = POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR;
338 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100339 }
340
341 ret = 0;
342
343exit:
344 fclose( f );
Andres Amaya Garciabeb42832017-07-12 10:36:30 +0100345 polarssl_zeroize( buf, sizeof( buf ) );
346
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100347 return( ret );
348}
349
350int hmac_drbg_update_seed_file( hmac_drbg_context *ctx, const char *path )
351{
Andres Amaya Garciabeb42832017-07-12 10:36:30 +0100352 int ret = 0;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100353 FILE *f;
354 size_t n;
355 unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ];
356
357 if( ( f = fopen( path, "rb" ) ) == NULL )
358 return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
359
360 fseek( f, 0, SEEK_END );
361 n = (size_t) ftell( f );
362 fseek( f, 0, SEEK_SET );
363
364 if( n > POLARSSL_HMAC_DRBG_MAX_INPUT )
365 {
366 fclose( f );
367 return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
368 }
369
370 if( fread( buf, 1, n, f ) != n )
Andres Amaya Garciabeb42832017-07-12 10:36:30 +0100371 ret = POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR;
372 else
373 hmac_drbg_update( ctx, buf, n );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100374
375 fclose( f );
376
Andres Amaya Garciabeb42832017-07-12 10:36:30 +0100377 polarssl_zeroize( buf, sizeof( buf ) );
378
379 if( ret != 0 )
380 return( ret );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100381
382 return( hmac_drbg_write_seed_file( ctx, path ) );
383}
384#endif /* POLARSSL_FS_IO */
385
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100386
387#if defined(POLARSSL_SELF_TEST)
388
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100389#if !defined(POLARSSL_SHA1_C)
390/* Dummy checkup routine */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100391int hmac_drbg_self_test( int verbose )
392{
393
394 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100395 polarssl_printf( "\n" );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100396
397 return( 0 );
398}
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100399#else
400
401#define OUTPUT_LEN 80
402
403/* From a NIST PR=true test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000404static const unsigned char entropy_pr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100405 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
406 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
407 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
408 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
409 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
410static const unsigned char result_pr[OUTPUT_LEN] = {
411 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
412 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
413 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
414 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
415 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
416 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
417 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
418
419/* From a NIST PR=false test vector */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000420static const unsigned char entropy_nopr[] = {
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100421 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
422 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
423 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
424 0xe9, 0x9d, 0xfe, 0xdf };
425static const unsigned char result_nopr[OUTPUT_LEN] = {
426 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
427 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
428 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
429 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
430 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
431 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
432 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
433
434/* "Entropy" from buffer */
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100435static size_t test_offset;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100436static int hmac_drbg_self_test_entropy( void *data,
437 unsigned char *buf, size_t len )
438{
439 const unsigned char *p = data;
440 memcpy( buf, p + test_offset, len );
441 test_offset += len;
442 return( 0 );
443}
444
Paul Bakker7dc4c442014-02-01 22:50:26 +0100445#define CHK( c ) if( (c) != 0 ) \
446 { \
447 if( verbose != 0 ) \
448 polarssl_printf( "failed\n" ); \
449 return( 1 ); \
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100450 }
451
452/*
453 * Checkup routine for HMAC_DRBG with SHA-1
454 */
455int hmac_drbg_self_test( int verbose )
456{
457 hmac_drbg_context ctx;
458 unsigned char buf[OUTPUT_LEN];
459 const md_info_t *md_info = md_info_from_type( POLARSSL_MD_SHA1 );
460
461 /*
462 * PR = True
463 */
464 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100465 polarssl_printf( " HMAC_DRBG (PR = True) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100466
467 test_offset = 0;
468 CHK( hmac_drbg_init( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000469 hmac_drbg_self_test_entropy, (void *) entropy_pr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100470 NULL, 0 ) );
471 hmac_drbg_set_prediction_resistance( &ctx, POLARSSL_HMAC_DRBG_PR_ON );
472 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
473 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
474 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
475 hmac_drbg_free( &ctx );
476
477 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100478 polarssl_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100479
480 /*
481 * PR = False
482 */
483 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100484 polarssl_printf( " HMAC_DRBG (PR = False) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100485
486 test_offset = 0;
487 CHK( hmac_drbg_init( &ctx, md_info,
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000488 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100489 NULL, 0 ) );
490 CHK( hmac_drbg_reseed( &ctx, NULL, 0 ) );
491 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
492 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
493 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
494 hmac_drbg_free( &ctx );
495
496 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100497 polarssl_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100498
499 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100500 polarssl_printf( "\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100501
502 return( 0 );
503}
504#endif /* POLARSSL_SHA1_C */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100505#endif /* POLARSSL_SELF_TEST */
506
507#endif /* POLARSSL_HMAC_DRBG_C */