blob: ed06cce833947fddf650496c3efd3b96349f0121 [file] [log] [blame]
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +01001/*
2 * HMAC_DRBG implementation (NIST SP 800-90)
3 *
Manuel Pégourié-Gonnarda658a402015-01-23 09:45:19 +00004 * Copyright (C) 2014, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +01005 *
Manuel Pégourié-Gonnard860b5162015-01-28 17:12:07 +00006 * This file is part of mbed TLS (https://polarssl.org)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +01007 *
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +01008 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
23/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010024 * The NIST SP 800-90A DRBGs are described in the following publication.
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010025 * http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010026 * References below are based on rev. 1 (January 2012).
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010027 */
28
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020029#if !defined(POLARSSL_CONFIG_FILE)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010030#include "polarssl/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020031#else
32#include POLARSSL_CONFIG_FILE
33#endif
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010034
35#if defined(POLARSSL_HMAC_DRBG_C)
36
37#include "polarssl/hmac_drbg.h"
38
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +010039#if defined(POLARSSL_FS_IO)
40#include <stdio.h>
41#endif
42
Paul Bakker7dc4c442014-02-01 22:50:26 +010043#if defined(POLARSSL_PLATFORM_C)
44#include "polarssl/platform.h"
45#else
46#define polarssl_printf printf
47#endif
48
Paul Bakker34617722014-06-13 17:20:13 +020049/* Implementation that should never be optimized out by the compiler */
50static void polarssl_zeroize( void *v, size_t n ) {
51 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
52}
53
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010054/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010055 * HMAC_DRBG update, using optional additional data (10.1.2.2)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010056 */
57void hmac_drbg_update( hmac_drbg_context *ctx,
58 const unsigned char *additional, size_t add_len )
59{
60 size_t md_len = ctx->md_ctx.md_info->size;
61 unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
62 unsigned char sep[1];
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +010063 unsigned char K[POLARSSL_MD_MAX_SIZE];
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010064
65 for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
66 {
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010067 /* Step 1 or 4 */
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +010068 md_hmac_reset( &ctx->md_ctx );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010069 md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
70 md_hmac_update( &ctx->md_ctx, sep, 1 );
71 if( rounds == 2 )
72 md_hmac_update( &ctx->md_ctx, additional, add_len );
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +010073 md_hmac_finish( &ctx->md_ctx, K );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010074
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010075 /* Step 2 or 5 */
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +010076 md_hmac_starts( &ctx->md_ctx, K, md_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010077 md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
78 md_hmac_finish( &ctx->md_ctx, ctx->V );
79 }
80}
81
82/*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +010083 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010084 */
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +010085int hmac_drbg_init_buf( hmac_drbg_context *ctx,
86 const md_info_t * md_info,
87 const unsigned char *data, size_t data_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010088{
89 int ret;
90
91 memset( ctx, 0, sizeof( hmac_drbg_context ) );
92
Paul Bakker84bbeb52014-07-01 14:53:22 +020093 md_init( &ctx->md_ctx );
94
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010095 if( ( ret = md_init_ctx( &ctx->md_ctx, md_info ) ) != 0 )
96 return( ret );
97
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +010098 /*
99 * Set initial working state.
100 * Use the V memory location, which is currently all 0, to initialize the
101 * MD context with an all-zero key. Then set V to its initial value.
102 */
103 md_hmac_starts( &ctx->md_ctx, ctx->V, md_info->size );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100104 memset( ctx->V, 0x01, md_info->size );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100105
106 hmac_drbg_update( ctx, data, data_len );
107
108 return( 0 );
109}
110
111/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100112 * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100113 */
114int hmac_drbg_reseed( hmac_drbg_context *ctx,
115 const unsigned char *additional, size_t len )
116{
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100117 unsigned char seed[POLARSSL_HMAC_DRBG_MAX_SEED_INPUT];
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100118 size_t seedlen;
119
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100120 /* III. Check input length */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100121 if( len > POLARSSL_HMAC_DRBG_MAX_INPUT ||
122 ctx->entropy_len + len > POLARSSL_HMAC_DRBG_MAX_SEED_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100123 {
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100124 return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100125 }
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100126
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100127 memset( seed, 0, POLARSSL_HMAC_DRBG_MAX_SEED_INPUT );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100128
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100129 /* IV. Gather entropy_len bytes of entropy for the seed */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100130 if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 )
131 return( POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
132
133 seedlen = ctx->entropy_len;
134
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100135 /* 1. Concatenate entropy and additional data if any */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100136 if( additional != NULL && len != 0 )
137 {
138 memcpy( seed + seedlen, additional, len );
139 seedlen += len;
140 }
141
142 /* 2. Update state */
143 hmac_drbg_update( ctx, seed, seedlen );
144
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100145 /* 3. Reset reseed_counter */
146 ctx->reseed_counter = 1;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100147
148 /* 4. Done */
149 return( 0 );
150}
151
152/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100153 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100154 */
155int hmac_drbg_init( hmac_drbg_context *ctx,
156 const md_info_t * md_info,
157 int (*f_entropy)(void *, unsigned char *, size_t),
158 void *p_entropy,
159 const unsigned char *custom,
160 size_t len )
161{
162 int ret;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100163 size_t entropy_len;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100164
165 memset( ctx, 0, sizeof( hmac_drbg_context ) );
166
Paul Bakker84bbeb52014-07-01 14:53:22 +0200167 md_init( &ctx->md_ctx );
168
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100169 if( ( ret = md_init_ctx( &ctx->md_ctx, md_info ) ) != 0 )
170 return( ret );
171
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100172 /*
173 * Set initial working state.
174 * Use the V memory location, which is currently all 0, to initialize the
175 * MD context with an all-zero key. Then set V to its initial value.
176 */
177 md_hmac_starts( &ctx->md_ctx, ctx->V, md_info->size );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100178 memset( ctx->V, 0x01, md_info->size );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100179
180 ctx->f_entropy = f_entropy;
181 ctx->p_entropy = p_entropy;
182
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100183 ctx->reseed_interval = POLARSSL_HMAC_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100184
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100185 /*
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100186 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
187 * each hash function, then according to SP800-90A rev1 10.1 table 2,
188 * min_entropy_len (in bits) is security_strength.
189 *
190 * (This also matches the sizes used in the NIST test vectors.)
191 */
192 entropy_len = md_info->size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
193 md_info->size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
194 32; /* better (256+) -> 256 bits */
195
196 /*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100197 * For initialisation, use more entropy to emulate a nonce
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100198 * (Again, matches test vectors.)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100199 */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100200 ctx->entropy_len = entropy_len * 3 / 2;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100201
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100202 if( ( ret = hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
203 return( ret );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100204
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100205 ctx->entropy_len = entropy_len;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100206
207 return( 0 );
208}
209
210/*
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100211 * Set prediction resistance
212 */
213void hmac_drbg_set_prediction_resistance( hmac_drbg_context *ctx,
214 int resistance )
215{
216 ctx->prediction_resistance = resistance;
217}
218
219/*
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100220 * Set entropy length grabbed for reseeds
221 */
222void hmac_drbg_set_entropy_len( hmac_drbg_context *ctx, size_t len )
223{
224 ctx->entropy_len = len;
225}
226
227/*
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100228 * Set reseed interval
229 */
230void hmac_drbg_set_reseed_interval( hmac_drbg_context *ctx, int interval )
231{
232 ctx->reseed_interval = interval;
233}
234
235/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100236 * HMAC_DRBG random function with optional additional data:
237 * 10.1.2.5 (arabic) + 9.3 (Roman)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100238 */
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100239int hmac_drbg_random_with_add( void *p_rng,
240 unsigned char *output, size_t out_len,
241 const unsigned char *additional, size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100242{
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100243 int ret;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100244 hmac_drbg_context *ctx = (hmac_drbg_context *) p_rng;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100245 size_t md_len = md_get_size( ctx->md_ctx.md_info );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100246 size_t left = out_len;
247 unsigned char *out = output;
248
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100249 /* II. Check request length */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100250 if( out_len > POLARSSL_HMAC_DRBG_MAX_REQUEST )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100251 return( POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
252
253 /* III. Check input length */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100254 if( add_len > POLARSSL_HMAC_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100255 return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
256
257 /* 1. (aka VII and IX) Check reseed counter and PR */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100258 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
259 ( ctx->prediction_resistance == POLARSSL_HMAC_DRBG_PR_ON ||
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100260 ctx->reseed_counter > ctx->reseed_interval ) )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100261 {
262 if( ( ret = hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
263 return( ret );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100264
265 add_len = 0; /* VII.4 */
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100266 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100267
268 /* 2. Use additional data if any */
269 if( additional != NULL && add_len != 0 )
270 hmac_drbg_update( ctx, additional, add_len );
271
272 /* 3, 4, 5. Generate bytes */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100273 while( left != 0 )
274 {
275 size_t use_len = left > md_len ? md_len : left;
276
Manuel Pégourié-Gonnardd742a032014-01-30 19:07:22 +0100277 md_hmac_reset( &ctx->md_ctx );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100278 md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
279 md_hmac_finish( &ctx->md_ctx, ctx->V );
280
281 memcpy( out, ctx->V, use_len );
282 out += use_len;
283 left -= use_len;
284 }
285
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100286 /* 6. Update */
287 hmac_drbg_update( ctx, additional, add_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100288
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100289 /* 7. Update reseed counter */
290 ctx->reseed_counter++;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100291
292 /* 8. Done */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100293 return( 0 );
294}
295
296/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100297 * HMAC_DRBG random function
298 */
299int hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
300{
301 return( hmac_drbg_random_with_add( p_rng, output, out_len, NULL, 0 ) );
302}
303
304/*
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100305 * Free an HMAC_DRBG context
306 */
307void hmac_drbg_free( hmac_drbg_context *ctx )
308{
309 if( ctx == NULL )
310 return;
311
312 md_free_ctx( &ctx->md_ctx );
313
Paul Bakker34617722014-06-13 17:20:13 +0200314 polarssl_zeroize( ctx, sizeof( hmac_drbg_context ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100315}
316
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100317#if defined(POLARSSL_FS_IO)
318int hmac_drbg_write_seed_file( hmac_drbg_context *ctx, const char *path )
319{
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100320 int ret;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100321 FILE *f;
322 unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ];
323
324 if( ( f = fopen( path, "wb" ) ) == NULL )
325 return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
326
327 if( ( ret = hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
328 goto exit;
329
330 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
331 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100332 ret = POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR;
333 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100334 }
335
336 ret = 0;
337
338exit:
339 fclose( f );
340 return( ret );
341}
342
343int hmac_drbg_update_seed_file( hmac_drbg_context *ctx, const char *path )
344{
345 FILE *f;
346 size_t n;
347 unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ];
348
349 if( ( f = fopen( path, "rb" ) ) == NULL )
350 return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
351
352 fseek( f, 0, SEEK_END );
353 n = (size_t) ftell( f );
354 fseek( f, 0, SEEK_SET );
355
356 if( n > POLARSSL_HMAC_DRBG_MAX_INPUT )
357 {
358 fclose( f );
359 return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
360 }
361
362 if( fread( buf, 1, n, f ) != n )
363 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100364 fclose( f );
365 return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100366 }
367
368 fclose( f );
369
370 hmac_drbg_update( ctx, buf, n );
371
372 return( hmac_drbg_write_seed_file( ctx, path ) );
373}
374#endif /* POLARSSL_FS_IO */
375
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100376
377#if defined(POLARSSL_SELF_TEST)
378
379#include <stdio.h>
380
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100381#if !defined(POLARSSL_SHA1_C)
382/* Dummy checkup routine */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100383int hmac_drbg_self_test( int verbose )
384{
385
386 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100387 polarssl_printf( "\n" );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100388
389 return( 0 );
390}
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100391#else
392
393#define OUTPUT_LEN 80
394
395/* From a NIST PR=true test vector */
396static unsigned char entropy_pr[] = {
397 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
398 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
399 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
400 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
401 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
402static const unsigned char result_pr[OUTPUT_LEN] = {
403 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
404 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
405 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
406 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
407 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
408 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
409 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
410
411/* From a NIST PR=false test vector */
412static unsigned char entropy_nopr[] = {
413 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
414 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
415 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
416 0xe9, 0x9d, 0xfe, 0xdf };
417static const unsigned char result_nopr[OUTPUT_LEN] = {
418 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
419 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
420 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
421 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
422 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
423 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
424 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
425
426/* "Entropy" from buffer */
Manuel Pégourié-Gonnard95924852014-03-21 10:54:55 +0100427static size_t test_offset;
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100428static int hmac_drbg_self_test_entropy( void *data,
429 unsigned char *buf, size_t len )
430{
431 const unsigned char *p = data;
432 memcpy( buf, p + test_offset, len );
433 test_offset += len;
434 return( 0 );
435}
436
Paul Bakker7dc4c442014-02-01 22:50:26 +0100437#define CHK( c ) if( (c) != 0 ) \
438 { \
439 if( verbose != 0 ) \
440 polarssl_printf( "failed\n" ); \
441 return( 1 ); \
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100442 }
443
444/*
445 * Checkup routine for HMAC_DRBG with SHA-1
446 */
447int hmac_drbg_self_test( int verbose )
448{
449 hmac_drbg_context ctx;
450 unsigned char buf[OUTPUT_LEN];
451 const md_info_t *md_info = md_info_from_type( POLARSSL_MD_SHA1 );
452
453 /*
454 * PR = True
455 */
456 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100457 polarssl_printf( " HMAC_DRBG (PR = True) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100458
459 test_offset = 0;
460 CHK( hmac_drbg_init( &ctx, md_info,
461 hmac_drbg_self_test_entropy, entropy_pr,
462 NULL, 0 ) );
463 hmac_drbg_set_prediction_resistance( &ctx, POLARSSL_HMAC_DRBG_PR_ON );
464 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
465 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
466 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
467 hmac_drbg_free( &ctx );
468
469 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100470 polarssl_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100471
472 /*
473 * PR = False
474 */
475 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100476 polarssl_printf( " HMAC_DRBG (PR = False) : " );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100477
478 test_offset = 0;
479 CHK( hmac_drbg_init( &ctx, md_info,
480 hmac_drbg_self_test_entropy, entropy_nopr,
481 NULL, 0 ) );
482 CHK( hmac_drbg_reseed( &ctx, NULL, 0 ) );
483 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
484 CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
485 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
486 hmac_drbg_free( &ctx );
487
488 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100489 polarssl_printf( "passed\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100490
491 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100492 polarssl_printf( "\n" );
Manuel Pégourié-Gonnard79afaa02014-01-31 11:12:09 +0100493
494 return( 0 );
495}
496#endif /* POLARSSL_SHA1_C */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100497#endif /* POLARSSL_SELF_TEST */
498
499#endif /* POLARSSL_HMAC_DRBG_C */