blob: 7a210925e003d8fa4a4a535cc1e1bca16fae3ca1 [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
Paul Bakker7dc4c442014-02-01 22:50:26 +010042#if defined(POLARSSL_PLATFORM_C)
43#include "polarssl/platform.h"
44#else
45#define polarssl_printf printf
46#endif
47
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010048/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010049 * HMAC_DRBG update, using optional additional data (10.1.2.2)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010050 */
51void hmac_drbg_update( hmac_drbg_context *ctx,
52 const unsigned char *additional, size_t add_len )
53{
54 size_t md_len = ctx->md_ctx.md_info->size;
55 unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
56 unsigned char sep[1];
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +010057 unsigned char K[POLARSSL_MD_MAX_SIZE];
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010058
59 for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
60 {
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010061 /* Step 1 or 4 */
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +010062 md_hmac_reset( &ctx->md_ctx );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010063 md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
64 md_hmac_update( &ctx->md_ctx, sep, 1 );
65 if( rounds == 2 )
66 md_hmac_update( &ctx->md_ctx, additional, add_len );
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +010067 md_hmac_finish( &ctx->md_ctx, K );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010068
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010069 /* Step 2 or 5 */
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +010070 md_hmac_starts( &ctx->md_ctx, K, md_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010071 md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
72 md_hmac_finish( &ctx->md_ctx, ctx->V );
73 }
74}
75
76/*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +010077 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010078 */
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +010079int hmac_drbg_init_buf( hmac_drbg_context *ctx,
80 const md_info_t * md_info,
81 const unsigned char *data, size_t data_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010082{
83 int ret;
84
85 memset( ctx, 0, sizeof( hmac_drbg_context ) );
86
87 if( ( ret = md_init_ctx( &ctx->md_ctx, md_info ) ) != 0 )
88 return( ret );
89
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +010090 /*
91 * Set initial working state.
92 * Use the V memory location, which is currently all 0, to initialize the
93 * MD context with an all-zero key. Then set V to its initial value.
94 */
95 md_hmac_starts( &ctx->md_ctx, ctx->V, md_info->size );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010096 memset( ctx->V, 0x01, md_info->size );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010097
98 hmac_drbg_update( ctx, data, data_len );
99
100 return( 0 );
101}
102
103/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100104 * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100105 */
106int hmac_drbg_reseed( hmac_drbg_context *ctx,
107 const unsigned char *additional, size_t len )
108{
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100109 unsigned char seed[POLARSSL_HMAC_DRBG_MAX_SEED_INPUT];
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100110 size_t seedlen;
111
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100112 /* III. Check input length */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100113 if( len > POLARSSL_HMAC_DRBG_MAX_INPUT ||
114 ctx->entropy_len + len > POLARSSL_HMAC_DRBG_MAX_SEED_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100115 {
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100116 return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100117 }
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100118
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100119 memset( seed, 0, POLARSSL_HMAC_DRBG_MAX_SEED_INPUT );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100120
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100121 /* IV. Gather entropy_len bytes of entropy for the seed */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100122 if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 )
123 return( POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
124
125 seedlen = ctx->entropy_len;
126
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100127 /* 1. Concatenate entropy and additional data if any */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100128 if( additional != NULL && len != 0 )
129 {
130 memcpy( seed + seedlen, additional, len );
131 seedlen += len;
132 }
133
134 /* 2. Update state */
135 hmac_drbg_update( ctx, seed, seedlen );
136
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100137 /* 3. Reset reseed_counter */
138 ctx->reseed_counter = 1;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100139
140 /* 4. Done */
141 return( 0 );
142}
143
144/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100145 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100146 */
147int hmac_drbg_init( hmac_drbg_context *ctx,
148 const md_info_t * md_info,
149 int (*f_entropy)(void *, unsigned char *, size_t),
150 void *p_entropy,
151 const unsigned char *custom,
152 size_t len )
153{
154 int ret;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100155 size_t entropy_len;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100156
157 memset( ctx, 0, sizeof( hmac_drbg_context ) );
158
159 if( ( ret = md_init_ctx( &ctx->md_ctx, md_info ) ) != 0 )
160 return( ret );
161
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100162 /*
163 * Set initial working state.
164 * Use the V memory location, which is currently all 0, to initialize the
165 * MD context with an all-zero key. Then set V to its initial value.
166 */
167 md_hmac_starts( &ctx->md_ctx, ctx->V, md_info->size );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100168 memset( ctx->V, 0x01, md_info->size );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100169
170 ctx->f_entropy = f_entropy;
171 ctx->p_entropy = p_entropy;
172
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100173 ctx->reseed_interval = POLARSSL_HMAC_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100174
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100175 /*
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100176 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
177 * each hash function, then according to SP800-90A rev1 10.1 table 2,
178 * min_entropy_len (in bits) is security_strength.
179 *
180 * (This also matches the sizes used in the NIST test vectors.)
181 */
182 entropy_len = md_info->size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
183 md_info->size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
184 32; /* better (256+) -> 256 bits */
185
186 /*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100187 * For initialisation, use more entropy to emulate a nonce
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100188 * (Again, matches test vectors.)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100189 */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100190 ctx->entropy_len = entropy_len * 3 / 2;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100191
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100192 if( ( ret = hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
193 return( ret );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100194
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100195 ctx->entropy_len = entropy_len;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100196
197 return( 0 );
198}
199
200/*
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100201 * Set prediction resistance
202 */
203void hmac_drbg_set_prediction_resistance( hmac_drbg_context *ctx,
204 int resistance )
205{
206 ctx->prediction_resistance = resistance;
207}
208
209/*
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100210 * Set entropy length grabbed for reseeds
211 */
212void hmac_drbg_set_entropy_len( hmac_drbg_context *ctx, size_t len )
213{
214 ctx->entropy_len = len;
215}
216
217/*
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100218 * Set reseed interval
219 */
220void hmac_drbg_set_reseed_interval( hmac_drbg_context *ctx, int interval )
221{
222 ctx->reseed_interval = interval;
223}
224
225/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100226 * HMAC_DRBG random function with optional additional data:
227 * 10.1.2.5 (arabic) + 9.3 (Roman)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100228 */
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100229int hmac_drbg_random_with_add( void *p_rng,
230 unsigned char *output, size_t out_len,
231 const unsigned char *additional, size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100232{
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100233 int ret;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100234 hmac_drbg_context *ctx = (hmac_drbg_context *) p_rng;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100235 size_t md_len = md_get_size( ctx->md_ctx.md_info );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100236 size_t left = out_len;
237 unsigned char *out = output;
238
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100239 /* II. Check request length */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100240 if( out_len > POLARSSL_HMAC_DRBG_MAX_REQUEST )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100241 return( POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
242
243 /* III. Check input length */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100244 if( add_len > POLARSSL_HMAC_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100245 return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
246
247 /* 1. (aka VII and IX) Check reseed counter and PR */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100248 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
249 ( ctx->prediction_resistance == POLARSSL_HMAC_DRBG_PR_ON ||
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100250 ctx->reseed_counter > ctx->reseed_interval ) )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100251 {
252 if( ( ret = hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
253 return( ret );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100254
255 add_len = 0; /* VII.4 */
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100256 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100257
258 /* 2. Use additional data if any */
259 if( additional != NULL && add_len != 0 )
260 hmac_drbg_update( ctx, additional, add_len );
261
262 /* 3, 4, 5. Generate bytes */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100263 while( left != 0 )
264 {
265 size_t use_len = left > md_len ? md_len : left;
266
Manuel Pégourié-Gonnardd742a032014-01-30 19:07:22 +0100267 md_hmac_reset( &ctx->md_ctx );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100268 md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
269 md_hmac_finish( &ctx->md_ctx, ctx->V );
270
271 memcpy( out, ctx->V, use_len );
272 out += use_len;
273 left -= use_len;
274 }
275
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100276 /* 6. Update */
277 hmac_drbg_update( ctx, additional, add_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100278
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100279 /* 7. Update reseed counter */
280 ctx->reseed_counter++;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100281
282 /* 8. Done */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100283 return( 0 );
284}
285
286/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100287 * HMAC_DRBG random function
288 */
289int hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
290{
291 return( hmac_drbg_random_with_add( p_rng, output, out_len, NULL, 0 ) );
292}
293
294/*
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100295 * Free an HMAC_DRBG context
296 */
297void hmac_drbg_free( hmac_drbg_context *ctx )
298{
299 if( ctx == NULL )
300 return;
301
302 md_free_ctx( &ctx->md_ctx );
303
304 memset( ctx, 0, sizeof( hmac_drbg_context ) );
305}
306
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100307#if defined(POLARSSL_FS_IO)
308int hmac_drbg_write_seed_file( hmac_drbg_context *ctx, const char *path )
309{
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100310 int ret;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100311 FILE *f;
312 unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ];
313
314 if( ( f = fopen( path, "wb" ) ) == NULL )
315 return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
316
317 if( ( ret = hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
318 goto exit;
319
320 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
321 {
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100322 ret = POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR; /* LCOV_EXCL_LINE */
323 goto exit; /* LCOV_EXCL_LINE */
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100324 }
325
326 ret = 0;
327
328exit:
329 fclose( f );
330 return( ret );
331}
332
333int hmac_drbg_update_seed_file( hmac_drbg_context *ctx, const char *path )
334{
335 FILE *f;
336 size_t n;
337 unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ];
338
339 if( ( f = fopen( path, "rb" ) ) == NULL )
340 return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
341
342 fseek( f, 0, SEEK_END );
343 n = (size_t) ftell( f );
344 fseek( f, 0, SEEK_SET );
345
346 if( n > POLARSSL_HMAC_DRBG_MAX_INPUT )
347 {
348 fclose( f );
349 return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
350 }
351
352 if( fread( buf, 1, n, f ) != n )
353 {
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100354 fclose( f ); /* LCOV_EXCL_LINE */
355 return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR ); /* LCOV_EXCL_LINE */
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100356 }
357
358 fclose( f );
359
360 hmac_drbg_update( ctx, buf, n );
361
362 return( hmac_drbg_write_seed_file( ctx, path ) );
363}
364#endif /* POLARSSL_FS_IO */
365
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100366
367#if defined(POLARSSL_SELF_TEST)
368
369#include <stdio.h>
370
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100371#if !defined(POLARSSL_SHA1_C)
372/* Dummy checkup routine */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100373int hmac_drbg_self_test( int verbose )
374{
375
376 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100377 polarssl_printf( "\n" );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100378
379 return( 0 );
380}
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100381#else
382
383#define OUTPUT_LEN 80
384
385/* From a NIST PR=true test vector */
386static unsigned char entropy_pr[] = {
387 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
388 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
389 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
390 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
391 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
392static const unsigned char result_pr[OUTPUT_LEN] = {
393 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
394 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
395 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
396 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
397 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
398 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
399 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
400
401/* From a NIST PR=false test vector */
402static unsigned char entropy_nopr[] = {
403 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
404 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
405 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
406 0xe9, 0x9d, 0xfe, 0xdf };
407static const unsigned char result_nopr[OUTPUT_LEN] = {
408 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
409 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
410 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
411 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
412 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
413 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
414 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
415
416/* "Entropy" from buffer */
417static int test_offset;
418static int hmac_drbg_self_test_entropy( void *data,
419 unsigned char *buf, size_t len )
420{
421 const unsigned char *p = data;
422 memcpy( buf, p + test_offset, len );
423 test_offset += len;
424 return( 0 );
425}
426
Paul Bakker7dc4c442014-02-01 22:50:26 +0100427#define CHK( c ) if( (c) != 0 ) \
428 { \
429 if( verbose != 0 ) \
430 polarssl_printf( "failed\n" ); \
431 return( 1 ); \
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100432 }
433
434/*
435 * Checkup routine for HMAC_DRBG with SHA-1
436 */
437int hmac_drbg_self_test( int verbose )
438{
439 hmac_drbg_context ctx;
440 unsigned char buf[OUTPUT_LEN];
441 const md_info_t *md_info = md_info_from_type( POLARSSL_MD_SHA1 );
442
443 /*
444 * PR = True
445 */
446 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100447 polarssl_printf( " HMAC_DRBG (PR = True) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100448
449 test_offset = 0;
450 CHK( hmac_drbg_init( &ctx, md_info,
451 hmac_drbg_self_test_entropy, entropy_pr,
452 NULL, 0 ) );
453 hmac_drbg_set_prediction_resistance( &ctx, POLARSSL_HMAC_DRBG_PR_ON );
454 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
455 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
456 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
457 hmac_drbg_free( &ctx );
458
459 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100460 polarssl_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100461
462 /*
463 * PR = False
464 */
465 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100466 polarssl_printf( " HMAC_DRBG (PR = False) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100467
468 test_offset = 0;
469 CHK( hmac_drbg_init( &ctx, md_info,
470 hmac_drbg_self_test_entropy, entropy_nopr,
471 NULL, 0 ) );
472 CHK( hmac_drbg_reseed( &ctx, NULL, 0 ) );
473 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
474 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
475 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
476 hmac_drbg_free( &ctx );
477
478 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100479 polarssl_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100480
481 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100482 polarssl_printf( "\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100483
484 return( 0 );
485}
486#endif /* POLARSSL_SHA1_C */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100487#endif /* POLARSSL_SELF_TEST */
488
489#endif /* POLARSSL_HMAC_DRBG_C */