blob: 30307b083bc5b8110183c8714b1e32f67805685a [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
Paul Bakker34617722014-06-13 17:20:13 +020052/* 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
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010057/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010058 * HMAC_DRBG update, using optional additional data (10.1.2.2)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010059 */
60void hmac_drbg_update( hmac_drbg_context *ctx,
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];
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +010066 unsigned char K[POLARSSL_MD_MAX_SIZE];
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010067
68 for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
69 {
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010070 /* Step 1 or 4 */
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +010071 md_hmac_reset( &ctx->md_ctx );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010072 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 );
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +010076 md_hmac_finish( &ctx->md_ctx, K );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010077
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010078 /* Step 2 or 5 */
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +010079 md_hmac_starts( &ctx->md_ctx, K, md_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010080 md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
81 md_hmac_finish( &ctx->md_ctx, ctx->V );
82 }
83}
84
85/*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +010086 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010087 */
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +010088int hmac_drbg_init_buf( hmac_drbg_context *ctx,
89 const md_info_t * md_info,
90 const unsigned char *data, size_t data_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010091{
92 int ret;
93
94 memset( ctx, 0, sizeof( hmac_drbg_context ) );
95
96 if( ( ret = md_init_ctx( &ctx->md_ctx, md_info ) ) != 0 )
97 return( ret );
98
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +010099 /*
100 * Set initial working state.
101 * Use the V memory location, which is currently all 0, to initialize the
102 * MD context with an all-zero key. Then set V to its initial value.
103 */
104 md_hmac_starts( &ctx->md_ctx, ctx->V, md_info->size );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100105 memset( ctx->V, 0x01, md_info->size );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100106
107 hmac_drbg_update( ctx, data, data_len );
108
109 return( 0 );
110}
111
112/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100113 * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100114 */
115int hmac_drbg_reseed( hmac_drbg_context *ctx,
116 const unsigned char *additional, size_t len )
117{
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100118 unsigned char seed[POLARSSL_HMAC_DRBG_MAX_SEED_INPUT];
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100119 size_t seedlen;
120
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100121 /* III. Check input length */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100122 if( len > POLARSSL_HMAC_DRBG_MAX_INPUT ||
123 ctx->entropy_len + len > POLARSSL_HMAC_DRBG_MAX_SEED_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100124 {
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100125 return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100126 }
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100127
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100128 memset( seed, 0, POLARSSL_HMAC_DRBG_MAX_SEED_INPUT );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100129
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100130 /* IV. Gather entropy_len bytes of entropy for the seed */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100131 if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 )
132 return( POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
133
134 seedlen = ctx->entropy_len;
135
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100136 /* 1. Concatenate entropy and additional data if any */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100137 if( additional != NULL && len != 0 )
138 {
139 memcpy( seed + seedlen, additional, len );
140 seedlen += len;
141 }
142
143 /* 2. Update state */
144 hmac_drbg_update( ctx, seed, seedlen );
145
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100146 /* 3. Reset reseed_counter */
147 ctx->reseed_counter = 1;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100148
149 /* 4. Done */
150 return( 0 );
151}
152
153/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100154 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100155 */
156int hmac_drbg_init( hmac_drbg_context *ctx,
157 const md_info_t * md_info,
158 int (*f_entropy)(void *, unsigned char *, size_t),
159 void *p_entropy,
160 const unsigned char *custom,
161 size_t len )
162{
163 int ret;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100164 size_t entropy_len;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100165
166 memset( ctx, 0, sizeof( hmac_drbg_context ) );
167
168 if( ( ret = md_init_ctx( &ctx->md_ctx, md_info ) ) != 0 )
169 return( ret );
170
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100171 /*
172 * Set initial working state.
173 * Use the V memory location, which is currently all 0, to initialize the
174 * MD context with an all-zero key. Then set V to its initial value.
175 */
176 md_hmac_starts( &ctx->md_ctx, ctx->V, md_info->size );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100177 memset( ctx->V, 0x01, md_info->size );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100178
179 ctx->f_entropy = f_entropy;
180 ctx->p_entropy = p_entropy;
181
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100182 ctx->reseed_interval = POLARSSL_HMAC_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100183
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100184 /*
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100185 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
186 * each hash function, then according to SP800-90A rev1 10.1 table 2,
187 * min_entropy_len (in bits) is security_strength.
188 *
189 * (This also matches the sizes used in the NIST test vectors.)
190 */
191 entropy_len = md_info->size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
192 md_info->size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
193 32; /* better (256+) -> 256 bits */
194
195 /*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100196 * For initialisation, use more entropy to emulate a nonce
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100197 * (Again, matches test vectors.)
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 * 3 / 2;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100200
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100201 if( ( ret = hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
202 return( ret );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100203
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100204 ctx->entropy_len = entropy_len;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100205
206 return( 0 );
207}
208
209/*
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100210 * Set prediction resistance
211 */
212void hmac_drbg_set_prediction_resistance( hmac_drbg_context *ctx,
213 int resistance )
214{
215 ctx->prediction_resistance = resistance;
216}
217
218/*
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100219 * Set entropy length grabbed for reseeds
220 */
221void hmac_drbg_set_entropy_len( hmac_drbg_context *ctx, size_t len )
222{
223 ctx->entropy_len = len;
224}
225
226/*
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100227 * Set reseed interval
228 */
229void hmac_drbg_set_reseed_interval( hmac_drbg_context *ctx, int interval )
230{
231 ctx->reseed_interval = interval;
232}
233
234/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100235 * HMAC_DRBG random function with optional additional data:
236 * 10.1.2.5 (arabic) + 9.3 (Roman)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100237 */
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100238int hmac_drbg_random_with_add( void *p_rng,
239 unsigned char *output, size_t out_len,
240 const unsigned char *additional, size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100241{
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100242 int ret;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100243 hmac_drbg_context *ctx = (hmac_drbg_context *) p_rng;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100244 size_t md_len = md_get_size( ctx->md_ctx.md_info );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100245 size_t left = out_len;
246 unsigned char *out = output;
247
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100248 /* II. Check request length */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100249 if( out_len > POLARSSL_HMAC_DRBG_MAX_REQUEST )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100250 return( POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
251
252 /* III. Check input length */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100253 if( add_len > POLARSSL_HMAC_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100254 return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
255
256 /* 1. (aka VII and IX) Check reseed counter and PR */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100257 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
258 ( ctx->prediction_resistance == POLARSSL_HMAC_DRBG_PR_ON ||
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100259 ctx->reseed_counter > ctx->reseed_interval ) )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100260 {
261 if( ( ret = hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
262 return( ret );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100263
264 add_len = 0; /* VII.4 */
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100265 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100266
267 /* 2. Use additional data if any */
268 if( additional != NULL && add_len != 0 )
269 hmac_drbg_update( ctx, additional, add_len );
270
271 /* 3, 4, 5. Generate bytes */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100272 while( left != 0 )
273 {
274 size_t use_len = left > md_len ? md_len : left;
275
Manuel Pégourié-Gonnardd742a032014-01-30 19:07:22 +0100276 md_hmac_reset( &ctx->md_ctx );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100277 md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
278 md_hmac_finish( &ctx->md_ctx, ctx->V );
279
280 memcpy( out, ctx->V, use_len );
281 out += use_len;
282 left -= use_len;
283 }
284
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100285 /* 6. Update */
286 hmac_drbg_update( ctx, additional, add_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100287
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100288 /* 7. Update reseed counter */
289 ctx->reseed_counter++;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100290
291 /* 8. Done */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100292 return( 0 );
293}
294
295/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100296 * HMAC_DRBG random function
297 */
298int hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
299{
300 return( hmac_drbg_random_with_add( p_rng, output, out_len, NULL, 0 ) );
301}
302
303/*
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100304 * Free an HMAC_DRBG context
305 */
306void hmac_drbg_free( hmac_drbg_context *ctx )
307{
308 if( ctx == NULL )
309 return;
310
311 md_free_ctx( &ctx->md_ctx );
312
Paul Bakker34617722014-06-13 17:20:13 +0200313 polarssl_zeroize( ctx, sizeof( hmac_drbg_context ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100314}
315
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100316#if defined(POLARSSL_FS_IO)
317int hmac_drbg_write_seed_file( hmac_drbg_context *ctx, const char *path )
318{
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100319 int ret;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100320 FILE *f;
321 unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ];
322
323 if( ( f = fopen( path, "wb" ) ) == NULL )
324 return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
325
326 if( ( ret = hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
327 goto exit;
328
329 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
330 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100331 ret = POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR;
332 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100333 }
334
335 ret = 0;
336
337exit:
338 fclose( f );
339 return( ret );
340}
341
342int hmac_drbg_update_seed_file( hmac_drbg_context *ctx, const char *path )
343{
344 FILE *f;
345 size_t n;
346 unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ];
347
348 if( ( f = fopen( path, "rb" ) ) == NULL )
349 return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
350
351 fseek( f, 0, SEEK_END );
352 n = (size_t) ftell( f );
353 fseek( f, 0, SEEK_SET );
354
355 if( n > POLARSSL_HMAC_DRBG_MAX_INPUT )
356 {
357 fclose( f );
358 return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
359 }
360
361 if( fread( buf, 1, n, f ) != n )
362 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100363 fclose( f );
364 return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100365 }
366
367 fclose( f );
368
369 hmac_drbg_update( ctx, buf, n );
370
371 return( hmac_drbg_write_seed_file( ctx, path ) );
372}
373#endif /* POLARSSL_FS_IO */
374
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100375
376#if defined(POLARSSL_SELF_TEST)
377
378#include <stdio.h>
379
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100380#if !defined(POLARSSL_SHA1_C)
381/* Dummy checkup routine */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100382int hmac_drbg_self_test( int verbose )
383{
384
385 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100386 polarssl_printf( "\n" );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100387
388 return( 0 );
389}
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100390#else
391
392#define OUTPUT_LEN 80
393
394/* From a NIST PR=true test vector */
395static unsigned char entropy_pr[] = {
396 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
397 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
398 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
399 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
400 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
401static const unsigned char result_pr[OUTPUT_LEN] = {
402 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
403 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
404 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
405 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
406 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
407 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
408 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
409
410/* From a NIST PR=false test vector */
411static unsigned char entropy_nopr[] = {
412 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
413 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
414 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
415 0xe9, 0x9d, 0xfe, 0xdf };
416static const unsigned char result_nopr[OUTPUT_LEN] = {
417 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
418 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
419 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
420 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
421 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
422 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
423 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
424
425/* "Entropy" from buffer */
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100426static size_t test_offset;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100427static int hmac_drbg_self_test_entropy( void *data,
428 unsigned char *buf, size_t len )
429{
430 const unsigned char *p = data;
431 memcpy( buf, p + test_offset, len );
432 test_offset += len;
433 return( 0 );
434}
435
Paul Bakker7dc4c442014-02-01 22:50:26 +0100436#define CHK( c ) if( (c) != 0 ) \
437 { \
438 if( verbose != 0 ) \
439 polarssl_printf( "failed\n" ); \
440 return( 1 ); \
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100441 }
442
443/*
444 * Checkup routine for HMAC_DRBG with SHA-1
445 */
446int hmac_drbg_self_test( int verbose )
447{
448 hmac_drbg_context ctx;
449 unsigned char buf[OUTPUT_LEN];
450 const md_info_t *md_info = md_info_from_type( POLARSSL_MD_SHA1 );
451
452 /*
453 * PR = True
454 */
455 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100456 polarssl_printf( " HMAC_DRBG (PR = True) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100457
458 test_offset = 0;
459 CHK( hmac_drbg_init( &ctx, md_info,
460 hmac_drbg_self_test_entropy, entropy_pr,
461 NULL, 0 ) );
462 hmac_drbg_set_prediction_resistance( &ctx, POLARSSL_HMAC_DRBG_PR_ON );
463 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
464 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
465 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
466 hmac_drbg_free( &ctx );
467
468 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100469 polarssl_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100470
471 /*
472 * PR = False
473 */
474 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100475 polarssl_printf( " HMAC_DRBG (PR = False) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100476
477 test_offset = 0;
478 CHK( hmac_drbg_init( &ctx, md_info,
479 hmac_drbg_self_test_entropy, entropy_nopr,
480 NULL, 0 ) );
481 CHK( hmac_drbg_reseed( &ctx, NULL, 0 ) );
482 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
483 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
484 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
485 hmac_drbg_free( &ctx );
486
487 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100488 polarssl_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100489
490 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100491 polarssl_printf( "\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100492
493 return( 0 );
494}
495#endif /* POLARSSL_SHA1_C */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100496#endif /* POLARSSL_SELF_TEST */
497
498#endif /* POLARSSL_HMAC_DRBG_C */