blob: d691be11f1e260a7230e76103dde4127a26fc273 [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
Paul Bakker84bbeb52014-07-01 14:53:22 +020096 md_init( &ctx->md_ctx );
97
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010098 if( ( ret = md_init_ctx( &ctx->md_ctx, md_info ) ) != 0 )
99 return( ret );
100
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100101 /*
102 * Set initial working state.
103 * Use the V memory location, which is currently all 0, to initialize the
104 * MD context with an all-zero key. Then set V to its initial value.
105 */
106 md_hmac_starts( &ctx->md_ctx, ctx->V, md_info->size );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100107 memset( ctx->V, 0x01, md_info->size );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100108
109 hmac_drbg_update( ctx, data, data_len );
110
111 return( 0 );
112}
113
114/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100115 * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100116 */
117int hmac_drbg_reseed( hmac_drbg_context *ctx,
118 const unsigned char *additional, size_t len )
119{
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100120 unsigned char seed[POLARSSL_HMAC_DRBG_MAX_SEED_INPUT];
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100121 size_t seedlen;
122
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100123 /* III. Check input length */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100124 if( len > POLARSSL_HMAC_DRBG_MAX_INPUT ||
125 ctx->entropy_len + len > POLARSSL_HMAC_DRBG_MAX_SEED_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100126 {
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100127 return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100128 }
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100129
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100130 memset( seed, 0, POLARSSL_HMAC_DRBG_MAX_SEED_INPUT );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100131
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100132 /* IV. Gather entropy_len bytes of entropy for the seed */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100133 if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 )
134 return( POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
135
136 seedlen = ctx->entropy_len;
137
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100138 /* 1. Concatenate entropy and additional data if any */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100139 if( additional != NULL && len != 0 )
140 {
141 memcpy( seed + seedlen, additional, len );
142 seedlen += len;
143 }
144
145 /* 2. Update state */
146 hmac_drbg_update( ctx, seed, seedlen );
147
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100148 /* 3. Reset reseed_counter */
149 ctx->reseed_counter = 1;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100150
151 /* 4. Done */
152 return( 0 );
153}
154
155/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100156 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100157 */
158int hmac_drbg_init( hmac_drbg_context *ctx,
159 const md_info_t * md_info,
160 int (*f_entropy)(void *, unsigned char *, size_t),
161 void *p_entropy,
162 const unsigned char *custom,
163 size_t len )
164{
165 int ret;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100166 size_t entropy_len;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100167
168 memset( ctx, 0, sizeof( hmac_drbg_context ) );
169
Paul Bakker84bbeb52014-07-01 14:53:22 +0200170 md_init( &ctx->md_ctx );
171
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100172 if( ( ret = md_init_ctx( &ctx->md_ctx, md_info ) ) != 0 )
173 return( ret );
174
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100175 /*
176 * Set initial working state.
177 * Use the V memory location, which is currently all 0, to initialize the
178 * MD context with an all-zero key. Then set V to its initial value.
179 */
180 md_hmac_starts( &ctx->md_ctx, ctx->V, md_info->size );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100181 memset( ctx->V, 0x01, md_info->size );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100182
183 ctx->f_entropy = f_entropy;
184 ctx->p_entropy = p_entropy;
185
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100186 ctx->reseed_interval = POLARSSL_HMAC_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100187
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100188 /*
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100189 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
190 * each hash function, then according to SP800-90A rev1 10.1 table 2,
191 * min_entropy_len (in bits) is security_strength.
192 *
193 * (This also matches the sizes used in the NIST test vectors.)
194 */
195 entropy_len = md_info->size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
196 md_info->size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
197 32; /* better (256+) -> 256 bits */
198
199 /*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100200 * For initialisation, use more entropy to emulate a nonce
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100201 * (Again, matches test vectors.)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100202 */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100203 ctx->entropy_len = entropy_len * 3 / 2;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100204
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100205 if( ( ret = hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
206 return( ret );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100207
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100208 ctx->entropy_len = entropy_len;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100209
210 return( 0 );
211}
212
213/*
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100214 * Set prediction resistance
215 */
216void hmac_drbg_set_prediction_resistance( hmac_drbg_context *ctx,
217 int resistance )
218{
219 ctx->prediction_resistance = resistance;
220}
221
222/*
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100223 * Set entropy length grabbed for reseeds
224 */
225void hmac_drbg_set_entropy_len( hmac_drbg_context *ctx, size_t len )
226{
227 ctx->entropy_len = len;
228}
229
230/*
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100231 * Set reseed interval
232 */
233void hmac_drbg_set_reseed_interval( hmac_drbg_context *ctx, int interval )
234{
235 ctx->reseed_interval = interval;
236}
237
238/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100239 * HMAC_DRBG random function with optional additional data:
240 * 10.1.2.5 (arabic) + 9.3 (Roman)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100241 */
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100242int hmac_drbg_random_with_add( void *p_rng,
243 unsigned char *output, size_t out_len,
244 const unsigned char *additional, size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100245{
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100246 int ret;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100247 hmac_drbg_context *ctx = (hmac_drbg_context *) p_rng;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100248 size_t md_len = md_get_size( ctx->md_ctx.md_info );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100249 size_t left = out_len;
250 unsigned char *out = output;
251
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100252 /* II. Check request length */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100253 if( out_len > POLARSSL_HMAC_DRBG_MAX_REQUEST )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100254 return( POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
255
256 /* III. Check input length */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100257 if( add_len > POLARSSL_HMAC_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100258 return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
259
260 /* 1. (aka VII and IX) Check reseed counter and PR */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100261 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
262 ( ctx->prediction_resistance == POLARSSL_HMAC_DRBG_PR_ON ||
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100263 ctx->reseed_counter > ctx->reseed_interval ) )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100264 {
265 if( ( ret = hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
266 return( ret );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100267
268 add_len = 0; /* VII.4 */
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100269 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100270
271 /* 2. Use additional data if any */
272 if( additional != NULL && add_len != 0 )
273 hmac_drbg_update( ctx, additional, add_len );
274
275 /* 3, 4, 5. Generate bytes */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100276 while( left != 0 )
277 {
278 size_t use_len = left > md_len ? md_len : left;
279
Manuel Pégourié-Gonnardd742a032014-01-30 19:07:22 +0100280 md_hmac_reset( &ctx->md_ctx );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100281 md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
282 md_hmac_finish( &ctx->md_ctx, ctx->V );
283
284 memcpy( out, ctx->V, use_len );
285 out += use_len;
286 left -= use_len;
287 }
288
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100289 /* 6. Update */
290 hmac_drbg_update( ctx, additional, add_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100291
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100292 /* 7. Update reseed counter */
293 ctx->reseed_counter++;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100294
295 /* 8. Done */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100296 return( 0 );
297}
298
299/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100300 * HMAC_DRBG random function
301 */
302int hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
303{
304 return( hmac_drbg_random_with_add( p_rng, output, out_len, NULL, 0 ) );
305}
306
307/*
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100308 * Free an HMAC_DRBG context
309 */
310void hmac_drbg_free( hmac_drbg_context *ctx )
311{
312 if( ctx == NULL )
313 return;
314
315 md_free_ctx( &ctx->md_ctx );
316
Paul Bakker34617722014-06-13 17:20:13 +0200317 polarssl_zeroize( ctx, sizeof( hmac_drbg_context ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100318}
319
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100320#if defined(POLARSSL_FS_IO)
321int hmac_drbg_write_seed_file( hmac_drbg_context *ctx, const char *path )
322{
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100323 int ret;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100324 FILE *f;
325 unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ];
326
327 if( ( f = fopen( path, "wb" ) ) == NULL )
328 return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
329
330 if( ( ret = hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
331 goto exit;
332
333 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
334 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100335 ret = POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR;
336 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100337 }
338
339 ret = 0;
340
341exit:
342 fclose( f );
343 return( ret );
344}
345
346int hmac_drbg_update_seed_file( hmac_drbg_context *ctx, const char *path )
347{
348 FILE *f;
349 size_t n;
350 unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ];
351
352 if( ( f = fopen( path, "rb" ) ) == NULL )
353 return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
354
355 fseek( f, 0, SEEK_END );
356 n = (size_t) ftell( f );
357 fseek( f, 0, SEEK_SET );
358
359 if( n > POLARSSL_HMAC_DRBG_MAX_INPUT )
360 {
361 fclose( f );
362 return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
363 }
364
365 if( fread( buf, 1, n, f ) != n )
366 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100367 fclose( f );
368 return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100369 }
370
371 fclose( f );
372
373 hmac_drbg_update( ctx, buf, n );
374
375 return( hmac_drbg_write_seed_file( ctx, path ) );
376}
377#endif /* POLARSSL_FS_IO */
378
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100379
380#if defined(POLARSSL_SELF_TEST)
381
382#include <stdio.h>
383
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100384#if !defined(POLARSSL_SHA1_C)
385/* Dummy checkup routine */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100386int hmac_drbg_self_test( int verbose )
387{
388
389 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100390 polarssl_printf( "\n" );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100391
392 return( 0 );
393}
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100394#else
395
396#define OUTPUT_LEN 80
397
398/* From a NIST PR=true test vector */
399static unsigned char entropy_pr[] = {
400 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
401 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
402 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
403 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
404 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
405static const unsigned char result_pr[OUTPUT_LEN] = {
406 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
407 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
408 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
409 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
410 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
411 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
412 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
413
414/* From a NIST PR=false test vector */
415static unsigned char entropy_nopr[] = {
416 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
417 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
418 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
419 0xe9, 0x9d, 0xfe, 0xdf };
420static const unsigned char result_nopr[OUTPUT_LEN] = {
421 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
422 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
423 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
424 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
425 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
426 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
427 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
428
429/* "Entropy" from buffer */
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100430static size_t test_offset;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100431static int hmac_drbg_self_test_entropy( void *data,
432 unsigned char *buf, size_t len )
433{
434 const unsigned char *p = data;
435 memcpy( buf, p + test_offset, len );
436 test_offset += len;
437 return( 0 );
438}
439
Paul Bakker7dc4c442014-02-01 22:50:26 +0100440#define CHK( c ) if( (c) != 0 ) \
441 { \
442 if( verbose != 0 ) \
443 polarssl_printf( "failed\n" ); \
444 return( 1 ); \
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100445 }
446
447/*
448 * Checkup routine for HMAC_DRBG with SHA-1
449 */
450int hmac_drbg_self_test( int verbose )
451{
452 hmac_drbg_context ctx;
453 unsigned char buf[OUTPUT_LEN];
454 const md_info_t *md_info = md_info_from_type( POLARSSL_MD_SHA1 );
455
456 /*
457 * PR = True
458 */
459 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100460 polarssl_printf( " HMAC_DRBG (PR = True) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100461
462 test_offset = 0;
463 CHK( hmac_drbg_init( &ctx, md_info,
464 hmac_drbg_self_test_entropy, entropy_pr,
465 NULL, 0 ) );
466 hmac_drbg_set_prediction_resistance( &ctx, POLARSSL_HMAC_DRBG_PR_ON );
467 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
468 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
469 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
470 hmac_drbg_free( &ctx );
471
472 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100473 polarssl_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100474
475 /*
476 * PR = False
477 */
478 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100479 polarssl_printf( " HMAC_DRBG (PR = False) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100480
481 test_offset = 0;
482 CHK( hmac_drbg_init( &ctx, md_info,
483 hmac_drbg_self_test_entropy, entropy_nopr,
484 NULL, 0 ) );
485 CHK( hmac_drbg_reseed( &ctx, NULL, 0 ) );
486 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
487 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
488 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
489 hmac_drbg_free( &ctx );
490
491 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100492 polarssl_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100493
494 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100495 polarssl_printf( "\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100496
497 return( 0 );
498}
499#endif /* POLARSSL_SHA1_C */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100500#endif /* POLARSSL_SELF_TEST */
501
502#endif /* POLARSSL_HMAC_DRBG_C */