blob: 619b4464edd630aed3c7c3e6f6726877da9d4e59 [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
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020032#if !defined(POLARSSL_CONFIG_FILE)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010033#include "polarssl/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020034#else
35#include POLARSSL_CONFIG_FILE
36#endif
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010037
38#if defined(POLARSSL_HMAC_DRBG_C)
39
40#include "polarssl/hmac_drbg.h"
41
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +010042#if defined(POLARSSL_FS_IO)
43#include <stdio.h>
44#endif
45
Paul Bakker7dc4c442014-02-01 22:50:26 +010046#if defined(POLARSSL_PLATFORM_C)
47#include "polarssl/platform.h"
48#else
49#define polarssl_printf printf
50#endif
51
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010052/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010053 * HMAC_DRBG update, using optional additional data (10.1.2.2)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010054 */
55void hmac_drbg_update( hmac_drbg_context *ctx,
56 const unsigned char *additional, size_t add_len )
57{
58 size_t md_len = ctx->md_ctx.md_info->size;
59 unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
60 unsigned char sep[1];
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +010061 unsigned char K[POLARSSL_MD_MAX_SIZE];
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010062
63 for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
64 {
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010065 /* Step 1 or 4 */
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +010066 md_hmac_reset( &ctx->md_ctx );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010067 md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
68 md_hmac_update( &ctx->md_ctx, sep, 1 );
69 if( rounds == 2 )
70 md_hmac_update( &ctx->md_ctx, additional, add_len );
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +010071 md_hmac_finish( &ctx->md_ctx, K );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010072
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010073 /* Step 2 or 5 */
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +010074 md_hmac_starts( &ctx->md_ctx, K, md_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010075 md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
76 md_hmac_finish( &ctx->md_ctx, ctx->V );
77 }
78}
79
80/*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +010081 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010082 */
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +010083int hmac_drbg_init_buf( hmac_drbg_context *ctx,
84 const md_info_t * md_info,
85 const unsigned char *data, size_t data_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010086{
87 int ret;
88
89 memset( ctx, 0, sizeof( hmac_drbg_context ) );
90
91 if( ( ret = md_init_ctx( &ctx->md_ctx, md_info ) ) != 0 )
92 return( ret );
93
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +010094 /*
95 * Set initial working state.
96 * Use the V memory location, which is currently all 0, to initialize the
97 * MD context with an all-zero key. Then set V to its initial value.
98 */
99 md_hmac_starts( &ctx->md_ctx, ctx->V, md_info->size );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100100 memset( ctx->V, 0x01, md_info->size );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100101
102 hmac_drbg_update( ctx, data, data_len );
103
104 return( 0 );
105}
106
107/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100108 * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100109 */
110int hmac_drbg_reseed( hmac_drbg_context *ctx,
111 const unsigned char *additional, size_t len )
112{
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100113 unsigned char seed[POLARSSL_HMAC_DRBG_MAX_SEED_INPUT];
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100114 size_t seedlen;
115
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100116 /* III. Check input length */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100117 if( len > POLARSSL_HMAC_DRBG_MAX_INPUT ||
118 ctx->entropy_len + len > POLARSSL_HMAC_DRBG_MAX_SEED_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100119 {
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100120 return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100121 }
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100122
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100123 memset( seed, 0, POLARSSL_HMAC_DRBG_MAX_SEED_INPUT );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100124
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100125 /* IV. Gather entropy_len bytes of entropy for the seed */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100126 if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 )
127 return( POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
128
129 seedlen = ctx->entropy_len;
130
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100131 /* 1. Concatenate entropy and additional data if any */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100132 if( additional != NULL && len != 0 )
133 {
134 memcpy( seed + seedlen, additional, len );
135 seedlen += len;
136 }
137
138 /* 2. Update state */
139 hmac_drbg_update( ctx, seed, seedlen );
140
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100141 /* 3. Reset reseed_counter */
142 ctx->reseed_counter = 1;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100143
144 /* 4. Done */
145 return( 0 );
146}
147
148/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100149 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100150 */
151int hmac_drbg_init( hmac_drbg_context *ctx,
152 const md_info_t * md_info,
153 int (*f_entropy)(void *, unsigned char *, size_t),
154 void *p_entropy,
155 const unsigned char *custom,
156 size_t len )
157{
158 int ret;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100159 size_t entropy_len;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100160
161 memset( ctx, 0, sizeof( hmac_drbg_context ) );
162
163 if( ( ret = md_init_ctx( &ctx->md_ctx, md_info ) ) != 0 )
164 return( ret );
165
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100166 /*
167 * Set initial working state.
168 * Use the V memory location, which is currently all 0, to initialize the
169 * MD context with an all-zero key. Then set V to its initial value.
170 */
171 md_hmac_starts( &ctx->md_ctx, ctx->V, md_info->size );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100172 memset( ctx->V, 0x01, md_info->size );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100173
174 ctx->f_entropy = f_entropy;
175 ctx->p_entropy = p_entropy;
176
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100177 ctx->reseed_interval = POLARSSL_HMAC_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100178
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100179 /*
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100180 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
181 * each hash function, then according to SP800-90A rev1 10.1 table 2,
182 * min_entropy_len (in bits) is security_strength.
183 *
184 * (This also matches the sizes used in the NIST test vectors.)
185 */
186 entropy_len = md_info->size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
187 md_info->size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
188 32; /* better (256+) -> 256 bits */
189
190 /*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100191 * For initialisation, use more entropy to emulate a nonce
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100192 * (Again, matches test vectors.)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100193 */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100194 ctx->entropy_len = entropy_len * 3 / 2;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100195
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100196 if( ( ret = hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
197 return( ret );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100198
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100199 ctx->entropy_len = entropy_len;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100200
201 return( 0 );
202}
203
204/*
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100205 * Set prediction resistance
206 */
207void hmac_drbg_set_prediction_resistance( hmac_drbg_context *ctx,
208 int resistance )
209{
210 ctx->prediction_resistance = resistance;
211}
212
213/*
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100214 * Set entropy length grabbed for reseeds
215 */
216void hmac_drbg_set_entropy_len( hmac_drbg_context *ctx, size_t len )
217{
218 ctx->entropy_len = len;
219}
220
221/*
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100222 * Set reseed interval
223 */
224void hmac_drbg_set_reseed_interval( hmac_drbg_context *ctx, int interval )
225{
226 ctx->reseed_interval = interval;
227}
228
229/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100230 * HMAC_DRBG random function with optional additional data:
231 * 10.1.2.5 (arabic) + 9.3 (Roman)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100232 */
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100233int hmac_drbg_random_with_add( void *p_rng,
234 unsigned char *output, size_t out_len,
235 const unsigned char *additional, size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100236{
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100237 int ret;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100238 hmac_drbg_context *ctx = (hmac_drbg_context *) p_rng;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100239 size_t md_len = md_get_size( ctx->md_ctx.md_info );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100240 size_t left = out_len;
241 unsigned char *out = output;
242
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100243 /* II. Check request length */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100244 if( out_len > POLARSSL_HMAC_DRBG_MAX_REQUEST )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100245 return( POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
246
247 /* III. Check input length */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100248 if( add_len > POLARSSL_HMAC_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100249 return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
250
251 /* 1. (aka VII and IX) Check reseed counter and PR */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100252 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
253 ( ctx->prediction_resistance == POLARSSL_HMAC_DRBG_PR_ON ||
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100254 ctx->reseed_counter > ctx->reseed_interval ) )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100255 {
256 if( ( ret = hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
257 return( ret );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100258
259 add_len = 0; /* VII.4 */
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100260 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100261
262 /* 2. Use additional data if any */
263 if( additional != NULL && add_len != 0 )
264 hmac_drbg_update( ctx, additional, add_len );
265
266 /* 3, 4, 5. Generate bytes */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100267 while( left != 0 )
268 {
269 size_t use_len = left > md_len ? md_len : left;
270
Manuel Pégourié-Gonnardd742a032014-01-30 19:07:22 +0100271 md_hmac_reset( &ctx->md_ctx );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100272 md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
273 md_hmac_finish( &ctx->md_ctx, ctx->V );
274
275 memcpy( out, ctx->V, use_len );
276 out += use_len;
277 left -= use_len;
278 }
279
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100280 /* 6. Update */
281 hmac_drbg_update( ctx, additional, add_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100282
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100283 /* 7. Update reseed counter */
284 ctx->reseed_counter++;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100285
286 /* 8. Done */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100287 return( 0 );
288}
289
290/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100291 * HMAC_DRBG random function
292 */
293int hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
294{
295 return( hmac_drbg_random_with_add( p_rng, output, out_len, NULL, 0 ) );
296}
297
298/*
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100299 * Free an HMAC_DRBG context
300 */
301void hmac_drbg_free( hmac_drbg_context *ctx )
302{
303 if( ctx == NULL )
304 return;
305
306 md_free_ctx( &ctx->md_ctx );
307
308 memset( ctx, 0, sizeof( hmac_drbg_context ) );
309}
310
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100311#if defined(POLARSSL_FS_IO)
312int hmac_drbg_write_seed_file( hmac_drbg_context *ctx, const char *path )
313{
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100314 int ret;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100315 FILE *f;
316 unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ];
317
318 if( ( f = fopen( path, "wb" ) ) == NULL )
319 return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
320
321 if( ( ret = hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
322 goto exit;
323
324 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
325 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100326 ret = POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR;
327 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100328 }
329
330 ret = 0;
331
332exit:
333 fclose( f );
334 return( ret );
335}
336
337int hmac_drbg_update_seed_file( hmac_drbg_context *ctx, const char *path )
338{
339 FILE *f;
340 size_t n;
341 unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ];
342
343 if( ( f = fopen( path, "rb" ) ) == NULL )
344 return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
345
346 fseek( f, 0, SEEK_END );
347 n = (size_t) ftell( f );
348 fseek( f, 0, SEEK_SET );
349
350 if( n > POLARSSL_HMAC_DRBG_MAX_INPUT )
351 {
352 fclose( f );
353 return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
354 }
355
356 if( fread( buf, 1, n, f ) != n )
357 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100358 fclose( f );
359 return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100360 }
361
362 fclose( f );
363
364 hmac_drbg_update( ctx, buf, n );
365
366 return( hmac_drbg_write_seed_file( ctx, path ) );
367}
368#endif /* POLARSSL_FS_IO */
369
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100370
371#if defined(POLARSSL_SELF_TEST)
372
373#include <stdio.h>
374
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100375#if !defined(POLARSSL_SHA1_C)
376/* Dummy checkup routine */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100377int hmac_drbg_self_test( int verbose )
378{
379
380 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100381 polarssl_printf( "\n" );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100382
383 return( 0 );
384}
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100385#else
386
387#define OUTPUT_LEN 80
388
389/* From a NIST PR=true test vector */
390static unsigned char entropy_pr[] = {
391 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
392 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
393 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
394 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
395 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
396static const unsigned char result_pr[OUTPUT_LEN] = {
397 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
398 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
399 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
400 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
401 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
402 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
403 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
404
405/* From a NIST PR=false test vector */
406static unsigned char entropy_nopr[] = {
407 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
408 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
409 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
410 0xe9, 0x9d, 0xfe, 0xdf };
411static const unsigned char result_nopr[OUTPUT_LEN] = {
412 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
413 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
414 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
415 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
416 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
417 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
418 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
419
420/* "Entropy" from buffer */
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100421static size_t test_offset;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100422static int hmac_drbg_self_test_entropy( void *data,
423 unsigned char *buf, size_t len )
424{
425 const unsigned char *p = data;
426 memcpy( buf, p + test_offset, len );
427 test_offset += len;
428 return( 0 );
429}
430
Paul Bakker7dc4c442014-02-01 22:50:26 +0100431#define CHK( c ) if( (c) != 0 ) \
432 { \
433 if( verbose != 0 ) \
434 polarssl_printf( "failed\n" ); \
435 return( 1 ); \
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100436 }
437
438/*
439 * Checkup routine for HMAC_DRBG with SHA-1
440 */
441int hmac_drbg_self_test( int verbose )
442{
443 hmac_drbg_context ctx;
444 unsigned char buf[OUTPUT_LEN];
445 const md_info_t *md_info = md_info_from_type( POLARSSL_MD_SHA1 );
446
447 /*
448 * PR = True
449 */
450 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100451 polarssl_printf( " HMAC_DRBG (PR = True) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100452
453 test_offset = 0;
454 CHK( hmac_drbg_init( &ctx, md_info,
455 hmac_drbg_self_test_entropy, entropy_pr,
456 NULL, 0 ) );
457 hmac_drbg_set_prediction_resistance( &ctx, POLARSSL_HMAC_DRBG_PR_ON );
458 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
459 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
460 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
461 hmac_drbg_free( &ctx );
462
463 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100464 polarssl_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100465
466 /*
467 * PR = False
468 */
469 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100470 polarssl_printf( " HMAC_DRBG (PR = False) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100471
472 test_offset = 0;
473 CHK( hmac_drbg_init( &ctx, md_info,
474 hmac_drbg_self_test_entropy, entropy_nopr,
475 NULL, 0 ) );
476 CHK( hmac_drbg_reseed( &ctx, NULL, 0 ) );
477 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
478 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
479 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
480 hmac_drbg_free( &ctx );
481
482 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100483 polarssl_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100484
485 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100486 polarssl_printf( "\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100487
488 return( 0 );
489}
490#endif /* POLARSSL_SHA1_C */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100491#endif /* POLARSSL_SELF_TEST */
492
493#endif /* POLARSSL_HMAC_DRBG_C */