blob: 33a20ef9cc78a992b533d14e7e1ffef42ac4d87d [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
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010042/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010043 * HMAC_DRBG update, using optional additional data (10.1.2.2)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010044 */
45void hmac_drbg_update( hmac_drbg_context *ctx,
46 const unsigned char *additional, size_t add_len )
47{
48 size_t md_len = ctx->md_ctx.md_info->size;
49 unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
50 unsigned char sep[1];
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +010051 unsigned char K[POLARSSL_MD_MAX_SIZE];
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010052
53 for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
54 {
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010055 /* Step 1 or 4 */
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +010056 md_hmac_reset( &ctx->md_ctx );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010057 md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
58 md_hmac_update( &ctx->md_ctx, sep, 1 );
59 if( rounds == 2 )
60 md_hmac_update( &ctx->md_ctx, additional, add_len );
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +010061 md_hmac_finish( &ctx->md_ctx, K );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010062
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010063 /* Step 2 or 5 */
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +010064 md_hmac_starts( &ctx->md_ctx, K, md_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010065 md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
66 md_hmac_finish( &ctx->md_ctx, ctx->V );
67 }
68}
69
70/*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +010071 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010072 */
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +010073int hmac_drbg_init_buf( hmac_drbg_context *ctx,
74 const md_info_t * md_info,
75 const unsigned char *data, size_t data_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010076{
77 int ret;
78
79 memset( ctx, 0, sizeof( hmac_drbg_context ) );
80
81 if( ( ret = md_init_ctx( &ctx->md_ctx, md_info ) ) != 0 )
82 return( ret );
83
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +010084 /*
85 * Set initial working state.
86 * Use the V memory location, which is currently all 0, to initialize the
87 * MD context with an all-zero key. Then set V to its initial value.
88 */
89 md_hmac_starts( &ctx->md_ctx, ctx->V, md_info->size );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010090 memset( ctx->V, 0x01, md_info->size );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010091
92 hmac_drbg_update( ctx, data, data_len );
93
94 return( 0 );
95}
96
97/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +010098 * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +010099 */
100int hmac_drbg_reseed( hmac_drbg_context *ctx,
101 const unsigned char *additional, size_t len )
102{
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100103 unsigned char seed[POLARSSL_HMAC_DRBG_MAX_SEED_INPUT];
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100104 size_t seedlen;
105
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100106 /* III. Check input length */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100107 if( len > POLARSSL_HMAC_DRBG_MAX_INPUT ||
108 ctx->entropy_len + len > POLARSSL_HMAC_DRBG_MAX_SEED_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100109 {
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100110 return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100111 }
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100112
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100113 memset( seed, 0, POLARSSL_HMAC_DRBG_MAX_SEED_INPUT );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100114
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100115 /* IV. Gather entropy_len bytes of entropy for the seed */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100116 if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 )
117 return( POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
118
119 seedlen = ctx->entropy_len;
120
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100121 /* 1. Concatenate entropy and additional data if any */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100122 if( additional != NULL && len != 0 )
123 {
124 memcpy( seed + seedlen, additional, len );
125 seedlen += len;
126 }
127
128 /* 2. Update state */
129 hmac_drbg_update( ctx, seed, seedlen );
130
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100131 /* 3. Reset reseed_counter */
132 ctx->reseed_counter = 1;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100133
134 /* 4. Done */
135 return( 0 );
136}
137
138/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100139 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100140 */
141int hmac_drbg_init( hmac_drbg_context *ctx,
142 const md_info_t * md_info,
143 int (*f_entropy)(void *, unsigned char *, size_t),
144 void *p_entropy,
145 const unsigned char *custom,
146 size_t len )
147{
148 int ret;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100149 size_t entropy_len;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100150
151 memset( ctx, 0, sizeof( hmac_drbg_context ) );
152
153 if( ( ret = md_init_ctx( &ctx->md_ctx, md_info ) ) != 0 )
154 return( ret );
155
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100156 /*
157 * Set initial working state.
158 * Use the V memory location, which is currently all 0, to initialize the
159 * MD context with an all-zero key. Then set V to its initial value.
160 */
161 md_hmac_starts( &ctx->md_ctx, ctx->V, md_info->size );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100162 memset( ctx->V, 0x01, md_info->size );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100163
164 ctx->f_entropy = f_entropy;
165 ctx->p_entropy = p_entropy;
166
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100167 ctx->reseed_interval = POLARSSL_HMAC_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100168
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100169 /*
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100170 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
171 * each hash function, then according to SP800-90A rev1 10.1 table 2,
172 * min_entropy_len (in bits) is security_strength.
173 *
174 * (This also matches the sizes used in the NIST test vectors.)
175 */
176 entropy_len = md_info->size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
177 md_info->size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
178 32; /* better (256+) -> 256 bits */
179
180 /*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100181 * For initialisation, use more entropy to emulate a nonce
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100182 * (Again, matches test vectors.)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100183 */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100184 ctx->entropy_len = entropy_len * 3 / 2;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100185
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100186 if( ( ret = hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
187 return( ret );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100188
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100189 ctx->entropy_len = entropy_len;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100190
191 return( 0 );
192}
193
194/*
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100195 * Set prediction resistance
196 */
197void hmac_drbg_set_prediction_resistance( hmac_drbg_context *ctx,
198 int resistance )
199{
200 ctx->prediction_resistance = resistance;
201}
202
203/*
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100204 * Set entropy length grabbed for reseeds
205 */
206void hmac_drbg_set_entropy_len( hmac_drbg_context *ctx, size_t len )
207{
208 ctx->entropy_len = len;
209}
210
211/*
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100212 * Set reseed interval
213 */
214void hmac_drbg_set_reseed_interval( hmac_drbg_context *ctx, int interval )
215{
216 ctx->reseed_interval = interval;
217}
218
219/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100220 * HMAC_DRBG random function with optional additional data:
221 * 10.1.2.5 (arabic) + 9.3 (Roman)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100222 */
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100223int hmac_drbg_random_with_add( void *p_rng,
224 unsigned char *output, size_t out_len,
225 const unsigned char *additional, size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100226{
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100227 int ret;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100228 hmac_drbg_context *ctx = (hmac_drbg_context *) p_rng;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100229 size_t md_len = md_get_size( ctx->md_ctx.md_info );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100230 size_t left = out_len;
231 unsigned char *out = output;
232
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100233 /* II. Check request length */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100234 if( out_len > POLARSSL_HMAC_DRBG_MAX_REQUEST )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100235 return( POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
236
237 /* III. Check input length */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100238 if( add_len > POLARSSL_HMAC_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100239 return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
240
241 /* 1. (aka VII and IX) Check reseed counter and PR */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100242 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
243 ( ctx->prediction_resistance == POLARSSL_HMAC_DRBG_PR_ON ||
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100244 ctx->reseed_counter > ctx->reseed_interval ) )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100245 {
246 if( ( ret = hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
247 return( ret );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100248
249 add_len = 0; /* VII.4 */
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100250 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100251
252 /* 2. Use additional data if any */
253 if( additional != NULL && add_len != 0 )
254 hmac_drbg_update( ctx, additional, add_len );
255
256 /* 3, 4, 5. Generate bytes */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100257 while( left != 0 )
258 {
259 size_t use_len = left > md_len ? md_len : left;
260
Manuel Pégourié-Gonnardd742a032014-01-30 19:07:22 +0100261 md_hmac_reset( &ctx->md_ctx );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100262 md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
263 md_hmac_finish( &ctx->md_ctx, ctx->V );
264
265 memcpy( out, ctx->V, use_len );
266 out += use_len;
267 left -= use_len;
268 }
269
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100270 /* 6. Update */
271 hmac_drbg_update( ctx, additional, add_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100272
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100273 /* 7. Update reseed counter */
274 ctx->reseed_counter++;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100275
276 /* 8. Done */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100277 return( 0 );
278}
279
280/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100281 * HMAC_DRBG random function
282 */
283int hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
284{
285 return( hmac_drbg_random_with_add( p_rng, output, out_len, NULL, 0 ) );
286}
287
288/*
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100289 * Free an HMAC_DRBG context
290 */
291void hmac_drbg_free( hmac_drbg_context *ctx )
292{
293 if( ctx == NULL )
294 return;
295
296 md_free_ctx( &ctx->md_ctx );
297
298 memset( ctx, 0, sizeof( hmac_drbg_context ) );
299}
300
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100301#if defined(POLARSSL_FS_IO)
302int hmac_drbg_write_seed_file( hmac_drbg_context *ctx, const char *path )
303{
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100304 int ret;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100305 FILE *f;
306 unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ];
307
308 if( ( f = fopen( path, "wb" ) ) == NULL )
309 return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
310
311 if( ( ret = hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
312 goto exit;
313
314 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
315 {
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100316 ret = POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR; /* LCOV_EXCL_LINE */
317 goto exit; /* LCOV_EXCL_LINE */
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100318 }
319
320 ret = 0;
321
322exit:
323 fclose( f );
324 return( ret );
325}
326
327int hmac_drbg_update_seed_file( hmac_drbg_context *ctx, const char *path )
328{
329 FILE *f;
330 size_t n;
331 unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ];
332
333 if( ( f = fopen( path, "rb" ) ) == NULL )
334 return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
335
336 fseek( f, 0, SEEK_END );
337 n = (size_t) ftell( f );
338 fseek( f, 0, SEEK_SET );
339
340 if( n > POLARSSL_HMAC_DRBG_MAX_INPUT )
341 {
342 fclose( f );
343 return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
344 }
345
346 if( fread( buf, 1, n, f ) != n )
347 {
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100348 fclose( f ); /* LCOV_EXCL_LINE */
349 return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR ); /* LCOV_EXCL_LINE */
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100350 }
351
352 fclose( f );
353
354 hmac_drbg_update( ctx, buf, n );
355
356 return( hmac_drbg_write_seed_file( ctx, path ) );
357}
358#endif /* POLARSSL_FS_IO */
359
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100360
361#if defined(POLARSSL_SELF_TEST)
362
363#include <stdio.h>
364
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100365#if !defined(POLARSSL_SHA1_C)
366/* Dummy checkup routine */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100367int hmac_drbg_self_test( int verbose )
368{
369
370 if( verbose != 0 )
371 printf( "\n" );
372
373 return( 0 );
374}
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100375#else
376
377#define OUTPUT_LEN 80
378
379/* From a NIST PR=true test vector */
380static unsigned char entropy_pr[] = {
381 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
382 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
383 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
384 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
385 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
386static const unsigned char result_pr[OUTPUT_LEN] = {
387 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
388 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
389 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
390 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
391 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
392 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
393 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
394
395/* From a NIST PR=false test vector */
396static unsigned char entropy_nopr[] = {
397 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
398 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
399 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
400 0xe9, 0x9d, 0xfe, 0xdf };
401static const unsigned char result_nopr[OUTPUT_LEN] = {
402 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
403 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
404 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
405 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
406 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
407 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
408 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
409
410/* "Entropy" from buffer */
411static int test_offset;
412static int hmac_drbg_self_test_entropy( void *data,
413 unsigned char *buf, size_t len )
414{
415 const unsigned char *p = data;
416 memcpy( buf, p + test_offset, len );
417 test_offset += len;
418 return( 0 );
419}
420
421#define CHK( c ) if( (c) != 0 ) \
422 { \
423 if( verbose != 0 ) \
424 printf( "failed\n" ); \
425 return( 1 ); \
426 }
427
428/*
429 * Checkup routine for HMAC_DRBG with SHA-1
430 */
431int hmac_drbg_self_test( int verbose )
432{
433 hmac_drbg_context ctx;
434 unsigned char buf[OUTPUT_LEN];
435 const md_info_t *md_info = md_info_from_type( POLARSSL_MD_SHA1 );
436
437 /*
438 * PR = True
439 */
440 if( verbose != 0 )
441 printf( " HMAC_DRBG (PR = True) : " );
442
443 test_offset = 0;
444 CHK( hmac_drbg_init( &ctx, md_info,
445 hmac_drbg_self_test_entropy, entropy_pr,
446 NULL, 0 ) );
447 hmac_drbg_set_prediction_resistance( &ctx, POLARSSL_HMAC_DRBG_PR_ON );
448 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
449 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
450 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
451 hmac_drbg_free( &ctx );
452
453 if( verbose != 0 )
454 printf( "passed\n" );
455
456 /*
457 * PR = False
458 */
459 if( verbose != 0 )
460 printf( " HMAC_DRBG (PR = False) : " );
461
462 test_offset = 0;
463 CHK( hmac_drbg_init( &ctx, md_info,
464 hmac_drbg_self_test_entropy, entropy_nopr,
465 NULL, 0 ) );
466 CHK( hmac_drbg_reseed( &ctx, NULL, 0 ) );
467 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
468 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
469 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
470 hmac_drbg_free( &ctx );
471
472 if( verbose != 0 )
473 printf( "passed\n" );
474
475 if( verbose != 0 )
476 printf( "\n" );
477
478 return( 0 );
479}
480#endif /* POLARSSL_SHA1_C */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100481#endif /* POLARSSL_SELF_TEST */
482
483#endif /* POLARSSL_HMAC_DRBG_C */